一般隐式转换会存在两个场景中:
- 数学运算符
- 逻辑语句中
数学运算符
数学运算符又分:加、减、乘、除
减、乘、除
我们在对各种非Number类型运用数学运算符(- * /)时,会先将非Number类型转换为Number类型。
例如:
1 - true // 0, 首先把 true 转换为数字 1, 然后执行 1 - 1
1 - null // 1, 首先把 null 转换为数字 0, 然后执行 1 - 0
1 * undefined // NaN, undefined 转换为数字是 NaN
2 * ['5'] // 10, ['5']首先会变成 '5', 然后再变成数字 5
其中最后一个例子是这样的,遇到引用类型先调用valueOf() 然后再调用 toString() 进行转换
加法比较特殊
优先级从上向下:
- 一侧为 String 类型时,另一侧会尽量转化成为字符串类型
- 一侧为 Number 类型时,且另一侧为基本数据类型,则另一侧会尽量转换成 Number 类型
- 一侧为 Number 类型,且另一侧为引用类型,会将它们俩都转换成 String 类型然后拼接
- 两侧都是基本类型,且都不是 String,Number。则两侧都会尽量向 Number 类型去转换
- 两侧都是引用类型,都转换成 String 类型然后拼接
例如:
/**规则一**/
"233" + 1 // "2331"
"233" + [] // "233"
/**规则二**/
123 + true // 124
123 + false // 123
123 + null // 123
123 + undefined // NaN
/**规则三**/
123 + [] // "123"
123 + [123] // "123123"
123 + {a: 1} // "123[object Object]"
/**规则四**/
true + null // 1
undefined + null // NaN
// 也可以得知:true => 1, false => 0 , null => 0 , undefined => NaN
/**规则五**/
[] + [] // ""
[123] + {a: 1} //"123[object Object]"
[] + function(a){console.log(a)} //"function(a){console.log(a)}"
逻辑语句中的类型转换
通常都是 if(xxx),或者while(xxx == xx) 还有for循环中也会判断逻辑,还有 ||,&&
单个变量 (也就是没有 == 的时候)
如果只有单个变量,会先将变量转换为Boolean值。(其实逻辑运算符也是单个单个地判断变量的)
0 && false // 0 因为 左边 0 优先转换为 false,然后因为是 && 所以就不看后面的了
"0" && false // false 因为 左边 "0" 优先转换为 true,然后因为是 && 继续去看后面,看见 false ,然后表达式的值就算 false了。
0 || false // false 因为 左边 0 优先转换为 false,因为是 || ,得继续看后面,所以表达式的结果是 false
"0" || false // "0" 因为 左边 "0" 优先转换为 true, 然后因为是 || 所以就不看后面的了
其中涉及的 || ,&& 逻辑运算符就不在这里赘述了。
使用 == 比较 (所以还是务必使用 === )
- NaN和其他任何类型比较永远返回 false(包括和他自己)。
- Boolean 和其他任何类型比较,Boolean 首先被转换为 Number 类型。
- String和Number比较,先将String转换为Number类型。
- null == undefined比较结果是true,除此之外,null、undefined和其他任何结果的比较值都为false。
- 原始类型和引用类型做比较时,引用类型会依照ToPrimitive规则转换为原始类型。
说人话就是:调用先valueOf然后调用toString。
如果还是没法得到一个原始类型,就会抛出 TypeError。
/**规则一**/
NaN == NaN // false
/**规则二**/
true == 1 // true
true == '2' // false, 先把 true 变成 1,而不是把 '2' 变成 true
true == ['1'] // true, 先把 true 变成 1, ['1']拆箱成 '1', 再参考规则3
true == ['2'] // false, 同上
undefined == false // false ,首先 false 变成 0,然后参考规则4
null == false // false,同上
/**规则三**/
123 == '123' // true, '123' 会先变成 123
'' == 0 // true, ''" 会首先变成 0
/**规则四**/
null == 0 //false, 虽然null有些时候会隐式转换成 0. 但这里是不相等的!
null == undefined //true
undefined == false // false
undefined == false // false
/**规则五**/
'[object Object]' == {a: 1} // true, 对象和字符串比较,对象通过 toString 得到一个基本类型值
'1,3' == [1, 3] // true ,同上
Tips
还有一种东西叫做 Object.is()
Object.is(value1, value2)
方法判断两个值是否为同一个值
简单概括一下它,
- 基本数据类型:就单纯的肉眼看长得一不一样,长得一样就是相等的,例如:
Object.is(NaN, NaN) // true
Object.is(+0, -0) // false
- 引用类型:地址一样就一样
Object.is({}, {}) //false
let a = {};
let b = a;
Object.is(a, b) //true
淦!为什么不用TS啊!!