今天在复习隐式转换的时候发现了一些盲点,首先简要回顾一下隐式转换规则。
+
加号,既可以是算术运算符,也可以是字符串连接符,规则为:
- 只要有一边是字符串,则是字符串连接符
- 两边都是数字,才是算术运算符
如果是其他类型,则调用相应的toString和Number()方法转换得到可运算的值。
一些特殊的toString和Number转换结果:
{ 1: 2 } // “[object Object]” NaN
[1, 2] // “1,2” NaN
function fn(){} // function函数体 NaN
undefined、null、true、false,toString均为本身的字符串,Number结果分别为NaN、0、1、0
1 + 'true' // "1true"
1 + true // 2
以上就是之前我对+隐式转换的了解,特殊类型+数字用Number,特殊类型+字符串用toString。
不过今天乱组合的时候发现了这样的情况
alert + ''
// "function alert() { [native code] }"
alert + 1
// "function alert() { [native code] }1"
[1, 2] + ''
// "1,2"
[1, 2] + 1
// "1,21"
function和array在+运算时只会进行字符串拼接操作。
{} + ''
// 0
'' + {}
// "[object Object]"
{} + 1
// 1
1 + {}
// "1[object Object]"
当{}在左边时,+总会被当成算术运算;当{}在右边时,+总会被当成字符串连接;无论另一边是什么类型。
这两个新规则也算是新盲点get。
隐式转换其他规则:
关系运算符
只有一边是string,将其他数据类型用Number进行转换再比较;
当两边都是string,比较其Unicode编码,string.charCodeAt;
如果是多字符,则依次比较:
2 > '10' // false 转成数字 2 > 10
'2' > '10' // true 都是字符串,比较'2'和'1'的Unicode编码
'abc' > 'aad' // 第一位相等,比较第二位,'b' > 'a',所以true
复杂数据类型
也就是最开始提到的对象、数组计算,规则是:
先用valueOf获取其原始值,如果不是Number类型(一般都不是,除非改写),则调用toString转成字符串,再转成number。转成什么类型视操作符及另一端决定。
经典题目:
if (a == 1 && a == 2 && a == 3) {
console.log('amazing')
}
// a = ?
// answer
a = {
i: 0,
valueOf: function() {
return ++a.i
}
}
这些也只是作为了解,知道复杂数据类型在隐式转换的过程中经历了哪些操作。
==
- !是Boolean()格式化比较,只要出现了,就都要转成布尔值比较。
- 都是引用类型,比较地址
[] 和 {} 转换结果都是true
[] == 0 // true 根据toString的结果,[]->"",Number("") -> 0 == 0
![] == 0 // true ![]->false == 0
[] == ![] // true []->""->0 == false<-![]
[] == [] // false 比较地址
{} == !{} // false {}->"[object Object]" != !{}->false
{} == {} // false 比较地址
学习隐式转换并不是在开发中偷工减料,而是防止误操作,以及了解这些原理能够更好地纠错。