先抛出简单结论
- 除了
二元加是优先转字符串,其他情况遇到数字都是优先转数字类型; - 布尔值会转换成数字。
细节则看下文。
正文
因为 JS 是弱类型语言,当遇到两个类型不同的值计算或逻辑比较等时,JS 底层会做隐式类型转换。
常见发生隐式类型转换的场景:一元加、各种运算操作、==、>, <, >=, <=、!xx等。
对象类型转原始类型
按toPrimitive规则转换:
- 通常情况是:
-
- 先调用
valueOf(),得到原始值则返回; - 还是非原始值则继续调用
toString(),得到原始值则返回; - 还不能得到原始值则报类型错误:提示不能将该值转换成原始值。
- 先调用
- Date 对象是个特殊。它改写了
toPrimitive:会优先调用toString(),不行再调用valueOf()。
-
- 需要注意的是: 遇到强制类型转换时,比如:
+new Date()此时则先valueOf(),因为这个方法返回的是数字类型。
- 需要注意的是: 遇到强制类型转换时,比如:
注意: [null]和[undefined]的原始值都是''。
1. 一元加 - ES5规范1.4.6
+xx
调用ToNumber处理值,相当于Number(xx)。也可以理解成强制类型转换成数字。
当xx为对象时,先按ToPrimitive规则将对象转换成原始值,再把原始值转换成数字类型。
1.1. 示例
scss
+[]
[].valueOf() // 返回值还是 []
[].toString() // 返回''
Number('') // 0
1.2. 几个特殊的细节
- 遇到
0b、0o、0x开头的:
-
- 会分别被当成二进制、八进制、十六进制,并返回对应十进制;
- 不管是字符串形式还是数字形式;
- 遇到多个
0开头的:
-
- 字符串形式是去除前导
0,返回剩余数字; - 数字形式则当成八进制数,并转换成十进制数返回。
- 字符串形式是去除前导
0b、0o、0x与后面的数字之间如果有数字会直接去掉。
arduino
// 1. 示例
+0b100 // 4
+0o100 // 64
+0x100 // 256
+'0b100' // 4
+'0o100' // 64
+'0x100' // 256
// 2. 示例
+000100 // 64
+'000100' // 100
// 3. 示例
+0x000100 // 256
+'0x000100' // 256
+'0x00000' // 0
2. 各种运算符
2.1. 除了+之外的其他运算符
- 先把运算符两边的值转换成数字类型;
- 再进行计算。
2.2. 二元加 - 规范/#x11.6.1
规则:
- 出现字符串类型值时,把其他值都调
toString()转换成字符串,然后字符串拼接;
-
'' + xxx.toString();- 注意: 同时出现有数字也是先把数字转换成字符串。这里跟
==情况刚好相反。
- 先执行上面情况, 出现对象类型先把对象类型按
ToPrimitive规则转换成原始值;此时的原始值通常都是字符串,所以执行字符串拼接; - 先执行上面情况, 出现数字及其他非字符串的基本类型值时,把基本类型值转换成数字类型;
-
2 + Number(null)
- 先执行上面情况,出现布尔值,先把布尔值转换成数字。
-
Number(true) + xxx
javascript
console.log(1 + undefined); // NaN
console.log('1' + undefined); // '1undefined'
console.log(1 + true); // 2
console.log({} + {}); // "[object Object][object Object]"
console.log(newDate(2017, 04, 21) + 1) // "Sun May 21 2017 00:00:00 GMT+0800 (CST)1"
3. ==双等 - 规范11.9.5
规则:
NaN不等于任何值,包括自己;undefined == null;
-
- 这两个值是相等的,但它们各自与其他任何值都不等。
- 数字和字符串:
-
- 先把字符串转换成数字,再比较。跟
二元加是相反的。1 == Number('1')
- 先把字符串转换成数字,再比较。跟
- 布尔值与其他:
-
- 先把布尔值转换成数字,再比较:
Number(true) == xxx
- 先把布尔值转换成数字,再比较:
- 对象与其他:
-
- 先执行上面情况, 把对象转换成原始值,再比较。
ini
// 转换规则:1 == Number('1'),而不是 String(1) == '1'
console.log(1 == '1') // true
// 注意不是 true == Boolean('2'),而是 Number(true) == '2'
console.log(true == '2') // false
3.1. 一些易错题
console.log([] == ![]) // true
-
![]转换成false;false转换成0;[]转换成'',然后转换成0;0==0 // true。
false==null
-
null==undefined只有这两个才相等,其他都不等。
'' == [null]、'' == [undefined]
-
- 数组的
toPrimitive规则决定的[null]和[undefined]的原始值都是''。
- 数组的
4. >, <, >=, <=
规则:
- 两边都是字符串,比较的是对应的字符编码值;
-
'2' > '10'实际比较的是'2'.charCodeAt() > '10'charCodeAt()
- 其他情况都是先转换成数字类型再比较。
5. 其他值转布尔值
除了这些是假值:undefined、null、false、 0、NaN、'';
其他都是true。