我对js隐式转换终于不用再靠_猜_了!
一、前言
在项目开发或者面试中经常出现下面这种判断:
console.log({} - {})
console.log([] - [])
console.log([] + [1, 2])
console.log([] == ![])
console.log({} == {})结果分别是:NaN、0、1,2、true、false
二、包装类
包装类是我们理解隐式转化的基础工具,是理解隐式转化的根基。js中包装类分为:Boolean()、Number()、String()。
Boolean()
Boolean()只有两种值:true和false
其中值为false的称为<font style="color:rgb(37, 41, 51);">falsey</font>或虚值,分别包括0、null、undefined、false、'',NaN;
Number()
Number()的处理就分为对 基础类型 的处理和 引用类型 的处理。
基础类型
console.log(Number(null)) // 0
console.log(Number(undefined)) // MaM
console.log(Number('1')) // 1
console.log(Number('')) // 0
console.log(Number(NaN)) // NaN
console.log(Number('1ab') // NaN
console.log(Number(false)) // 0
console.log(Number(true)) // 1其中为NaN的数值分别有undefined、null、'1ab'
null表示"没有对象",即该处不应该有值。 undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。
而'1ab'为NaN是因为字符串转换中出现了非数字的就会转换成NaN
引用类型
假如我们现在有下面这么一个对象:
const obj = {
toString() {
return 2
},
valueOf() {
return 1
}
}如果用Number()去取值的时候就会调用到valueOf()方法,此时会返回 1 ,但如果改写 valueOf() { return {} }的话就会去调用 toString(), 此时返回 2
所以Number(引用类型)的逻辑过程就是:

画板
String()
String()就是跟Number()相反,先调用toString()然后再看valueOf()
const obj = {
toString() {
return {}
},
valueOf() {
return 1
}
}
console.log(String(obj)) // 1
console.log(String({})) // [object Object]3 < 2 < 1 和 2 < 1 < 1
两个输出都是true,第一个符合数学公式,第二个就涉及到隐式转换了
- 比较 2 < 1 结果为 fasle
- 现在就是 false < 1 ,Number(false) 为0
- 现在就是 0 < 1, 结果为 true
三、隐式转换规则
boolean 隐式转换触发
- if
- switch
- while
- for(;;)
- &&
- ||
- !
- !!
- ? : 三元运算
number 隐式转换触发
用到数字运算符的地方都会进行转换:+ - * / == ~~ & | ~ ^ << <<<
string 隐式转换触发
+ 且两边大于等于1个string类型. 除了有 symbol类型之外
console.log(1 + '2' + '2') // '122'
console.log(1 + + '2' + '2') // '32'
console.log('A' - 'B' + '2') // 'NaN2'
console.log('A' - 'B' + 2) // NaN- 用 + 包裹,全部就转换为字符串后相加操作
- +'2' 会先进行 number 转换,变成1 + 2 = 3,然后遇到 + 在进行string转换
- 'A' - 'B' 会先进行 number 转换,变成 NaN,然后string转换
- 同上
四、需要注意的点
console.log((123).toString()) // 123
console.log(undefined.toString()) // 报错
console.log(null.toString()) // 报错undefined和null并没有包装类,它们是基础类型,所以没有toString()方法
五、面试题
console.log([] == ![]) // true- 一看到
==就会想到两边会进行Number转换 Number([])会调用到Array.prototype.toSting(),得到的是一个空字符串'',用Number转换后就会变成0- 右边
![]会先进行Boolean转换,[]不是falsey,所以Boolean([])为true !true再进行Numebr转换就会变成 0- 所以最终就是
0 == 0,结果为true
六、奇奇怪怪的题目
66.toString() // 报错: Invalid or unexpected token
66..toString() // '66'
66.6.toString() // '66.6'
66...toString() // 报错: Unexpected token '.'