先抛出简单结论
- 除了
二元加
是优先转字符串,其他情况遇到数字都是优先转数字类型; - 布尔值会转换成数字。
细节则看下文。
正文
因为 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
。