转载

“JS高程”读书笔记0

结合ES5,重读《JavaScript高级程序设计》,希望把书读薄点儿。 刚开头,看了下数据类型,这里主要记录了Null、Boolean、Number

数据类型

6种数据类型:

  • 5种简单数据类型(基本数据类型):
    • Undefined Null Boolean String Number
  • 1种复杂数据类型:
    • Object

typof的返回值有: "undefined" "object" "boolean" "string" "number" "function"

ECMAScript关于typeof操作的定义 The typeof Operator

null

对比发现,少了null,因为null表示一个空对象的指针:

typeof null; // "object" 

undefined

// 未定义的 // var age  // 未初始化的 var msg;  // 调用方法 console.log(age);      // 报错 console.log(msg);      // undefined 

但是typeof方法返回的是同一个值:

typeof age;      // undefined typeof msg;       // undefined 

undefined & null

undefined是派生自null的,ECMA-262规定他俩的相等性检测,返回true

undefined == null;       // true 

这里处于比较的目的,是做了操作数转换的,因此,严格模式下并不相等:

undefined === null;      // false 

number

采用IEEE754格式来表示整数和浮点数( 因此也拥有IEEE754对于浮点数处理的bug )

Infinity无法参与数值计算,可用isFinite函数来检测:

var a = Number.MAX_VALUE + Number.MIN_VALUE; console.log(isFinite(a));   // true 

NaN——非数值(Not a Number),同时无法转换成数值,与任何值都不想等,可用isNaN检测:

NaN == NaN;          // false isNaN(NaN);           // true isNaN("10");        // false,可以被转换成数值 isNaN(false);     // false,可以被转换成数值 isNaN("number");    // true,非数值,同时,无法被转换成数值 

isNaN同样可以用来检测对象,在基于对象调用isNaN函数时,会首先调用valueOf()方法,然后确定该方法的返回值是否可以转换为数值。 如果不能,则基于这个返回值再调用toString()方法,再测试返回值。 这个过程也是ECMAScript中内置函数和操作符的一般执行流程。

valueOf() & toString()

valueOf()与toString()是 所有ECMAScript对象拥有的内置方法 。操作对象时,valueOf()和toString()会被隐式的调用。

valueOf()方法的目的是将对象转换成最有意义的原始值([[PrimitiveValue]])。即ECMAScript的5种基本类型中的三种,布尔值、数字、字符串。

true.valueOf();          // true 1..valueOf();         // 1 'str'.valueOf();      // "str" null.valueOf();           // TypeError undefined.valueOf();  // TypeError ({k: 'v'}).valueOf();   // {k: 'v'},对象本身 [1,2,3].valueOf();       // [1,2,3],数组本身 

ECMAScript-262中 这样描述valueOf() 方法:

When the valueOf method is called, the following steps are taken:

  1. Let O be the result of calling ToObject passing the this value as the argument.
  2. If O is the result of calling the Object constructor with a host object ( 15.2.2.1 ), then
    • Return either O or another value such as the host object originally passed to the constructor. The specific result that is returned is implementation-defined.
  3. Return O .

当valueOf方法被调用时,会调用内置的ToObject,并将 this 作为参数传进去。ToObject检测会根据参数类型进行数值的转换:

  • Undefined - 抛出 TypeError 异常
  • Null - 抛出 TypeError 异常
  • Boolean - 创建一个Boolean对象,调用 ToBoolean 生成[[PrimitiveValue]]
  • Number - 创建一个Number对象,调用 ToNumber 生成[[PrimitiveValue]]
  • String - 创建一个String对象,调用 ToString 生成[[PrimitiveValue]]
  • Object - 对象本身

toString()方法的目的是将对象转换成一个有意义的字符串。

true.toString();                             // "true" 1..toString();                                    // "1" 'str'.toString();                             // "str" null.toString();                              // TypeError Object.prototype.toString.call(null);            // "[object Null]" undefined.toString();                         // TypeError Object.prototype.toString.call(undefined);       // "[object Undefined]" ({k: 'v'}).toString();                          // "[object Object]" [1,2,3].toString();                              // "1,2,3" 

ECMAScript对象的大多数操作的转换结果是字符串,这两个方法的结果是相同的。但是如果操作的对象为Number、Boolean或者Date,结果就不同了。

简单来说,在对像操作的隐式转换时,先根据前文线索(hint),如果hint是String,即字符串操作,则先调用toString()方法,没有返回值,再调用valueOf()方法;如果hint是Number,则正好相反。如果没有hint,则默认hint为Number。参见 [[DefaultValue]] (hint) 。

var obj = {  toString: function() {   return 'invoke toString';  },  valueOf: function() {   return 123;  } }; obj + '!';  // "123!" alert(obj);    // "invoke toString"  

关于toString和valueOf的转换见此文 Conversion, toString and valueOf 。有时间,再把他翻译了

关于对象的原始值(Object to PrimitiveValue)的转换,可以参考这篇文章 Object-to-Primitive Conversions in JavaScript

关于+操作,首先计算左边表达式,调用GetValue()取得左边表达式的值;再计算右边表达式,调用GetValue()取得右边的值;之后将左边value求原始值(primitiveValue),再求右边原始值; 如果左边或者右边原始值是string,则调用ToString拼接字符串;否则,调用ToNumber求和。 参见 The Addition operator ( + )

数值转换

有3个函数可以将非数值转换为数值:Number()、parseInt()和parseFloat()。

Number

Number()可以将任何非数值,转换为数值。 Number ( [ value ] ) ,将调用 ToNumber 来计算返回值:

  • Undefined - NaN
  • Null - +0
  • Boolean - true -> 1,false -> 0
  • Number - 原值,不做转换
  • Object -
    • 通过 ToPrimitive() 获得原始值
    • 再调用ToNumber()

对于字符串的操作比较复杂:

  • 只包含数字 - 转换为 10进制 数值,前导的0会被忽略,
  • 只包含有效浮点数 - 转为浮点数值,忽略前导0
  • 只包含有效十六进制数 - 转为相同的十进制数值
  • 空字符串 - 0
  • 不符合上述条件的 - NaN
Number("00123");       // 123 Number("01.1");         // 1.1 Number("0xf11");        // 3857 Number("");             // 0 Number("00xf11");       // NaN 

parseInt()

parseInt(string, radix)方法,用于将字符串(string)转为响应进制(radix)的整形数字。

字符串(string)将忽略前导0、空格和其他制表符(/n、/t、/r)。

radix未定义或者是0,则默认以10进制计算。除非string是以 0x 或者 0X 开头的(将以16进制计算)。如果设置了radix为16进制,可以选择是否以 0x0X 开头。

ES3(ECMAScript-262 第三版)中会默认以0开头的,浏览器实现上可以按8进制计算,或者按10进制,但是ES5中已经去掉,即按10进制计算。类似的,《高程(第2版)》第3.4节Number类型(27页),关于 parseInt('070') 为默认以8进制计算的说法,目前是不适用的

parseInt('00000012.2');              // 0 parseInt('  0000 /t/n/r 12.2');       // 0 parseInt('  /t/r/n000012.2');     // 12 parseInt(' 0000012 ') * 2;          // 24 0000012 * 2;                      // 10 

parseInt被调用时:

  • 去掉前导的空格和制表符
  • 设置为正数
  • 如果 - 开头,则为负数
  • 设置位数radix
  • 去掉 0x 或者 0X 前缀,如果剩余为空,返回NaN
  • 遇到第一个数字,开始解析,直到遇到第一个非数字,停止解析,返回结果

参见 parseInt (string , radix)

parseFloat()不再介绍,详情见 parseFloat (string)

测验

这里有一套题 Are You a JavaScript Guru? Try This Test(需翻墙) ,其中至少有十道题都多多少少涉及这一部分相关的内容:

  1. ++Math.PI
  2. (0.1 + 0.2) + 0.3 == 0.1 + (0.2 + 0.3)
  3. typeof NaN
  4. typeof typeof undefined
  5. a = {null:null}; typeof a.null;
  6. a = "5"; b = "2"; c = a * b;
  7. a = "5"; b = 2; c = a+++b;
  8. isNaN(1/null)
  9. (16).toString(16)
  10. 016 * 2
  11. ~null
  12. "ab c".match(//b/w/b/)

答案是(请自行翻译):

这里还有一套题 Test – Are you a Javascript Guru? (表打我,鲁迅先生《野草集》都有“我家门前有两棵树,一颗是枣树,另一颗还是枣树”的经典,我也用下……),其中至少五道题与这次内容相关。

计算result的指:

  1. var result = [10] + 1;
  2. var result = ['a', 'b', 'c'] + "";
  3. var result = 'a' + 5;
  4. var result = 3.75 | 0;
  5. var result = 65 / 'a';
  6. var ob = {"10": 1}; ob[10] = 2; ob[[1, 0]] = 3; var result = ob["10"] + ob[10] + ob[[1, 05. ]];
  7. var $ = {"": String}; var result = !!$ ([]) ;
  8. var result = (' /t/r/n ' == 0);
  9. var a = new String("123"); var b = "123"; var result = (a === b);
  10. var a = {key: 1}; var b = {key: 1}; var result = (a == b);

答案是(请自行翻译):

这里还有一套专门针对数值转换的题目—— JavaScript Quiz [x + 0 == x - 0]

正文到此结束
Loading...