true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
"true" == true
false == "false"
null == ""
!!"false" == !!"true"
["x"] == "x"
[] + null + 1
0 || "0" && {}
[1,2,3] == [1,2,3]
{} + [] + {} + [1]
! + [] + [] + ![]
new Date(0) - 0
new Date(0) + 0
答案解析
接下来我们按照之前的转换逻辑来解释一下每一道题,看一下是否和你的答案一样。
true + false // 1
‘+’ 运算符会触发 number 类型转换对于 true 和 false
12 / '6' // 2
算数运算符会把字符串 ‘6’ 转为 number 类型
"number" + 15 + 3 // "number153"
‘+’ 运算符按从左到右的顺序的执行,所以优先执行 “number” + 15, 把 15 转为 string 类型,得到 “number15” 然后同理执行 “number15” + 3
15 + 3 + "number" // "18number"
15 + 3 先执行,运算符两边都是 number 类型 ,不用转换,然后执行 18 + “number” 最终得到 “18number”
[1] > null // true
==> '1' > 0
==> 1 > 0
==> true
复制代码
比较运算符 > 执行 number 类型隐式转换。
"foo" + + "bar" // "fooNaN"
==> "foo" + (+"bar")
==> "foo" + NaN
==> "fooNaN"
复制代码
一元 + 运算符比二元 + 运算符具有更高的优先级。所以 + bar表达式先求值。一元加号执行字符串“bar” 的 number 类型转换。因为字符串不代表一个有效的数字,所以结果是NaN。在第二步中,计算表达式’foo’ + NaN。
'true' == true // false
==> NaN == 1
==> false
'false' == false // false
==> NaN == 0
==> false
复制代码
== 运算符执行 number 类型转换,’true’ 转换为 NaN, boolean 类型 true 转换为 1
null == '' // false
复制代码
null 不等于任何值除了 null 和 undefined
!!"false" == !!"true" // true
==> true == true
==> true
复制代码
!! 运算符将字符串 ‘true’ 和 ‘false’ 转为 boolean 类型 true, 因为不是空字符串,然后两边都是 boolean 型不在执行隐式转换操作。
['x'] == 'x' // true
复制代码
== 运算符对数组类型执行 number 转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 ‘x’
[] + null + 1 // 'null1'
==> '' + null + 1
==> 'null' + 1
==> 'null1'
复制代码
‘+’ 运算符执行 number 类型转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 ‘’, 接下来执行表达式 ‘’ + null + 1。
0 || "0" && {} // {}
==> (0 || '0') && {}
==> (false || true) && {}
==> true && {}
==> {}
复制代码
逻辑运算符 || 和 && 将值转为 boolean 型,但是会返回原始值(不是 boolean)。
[1,2,3] == [1,2,3] // false
复制代码
当运算符两边类型相同时,不会执行类型转换,两个数组的内存地址不一样,所以返回 false
{} + [] + {} + [1] // '0[object Object]1'
==> +[] + {} + [1]
==> 0 + {} + [1]
==> 0 + '[object Object]' + '1'
==> '0[object Object]1'
复制代码
所有的操作数都不是原始类型,所以会按照从左到右的顺序执行 number 类型的隐式转换, object 和 array 类型的 valueOf() 方法返回它们本身,所以直接忽略,执行 toString() 方法。 这里的技巧是,第一个 {} 不被视为 object,而是块声明语句,因此它被忽略。计算从 +[] 表达式开始,该表达式通过toString()方法转换为空字符串,然后转换为0。
! + [] + [] + ![] // 'truefalse'
==> !(+[]) + [] + (![])
==> !0 + [] + false
==> true + [] + false
==> true + '' + false
==> 'truefalse'
复制代码
一元运算符优先执行,+[] 转为 number 类型 0,![] 转为 boolean 型 false。
new Date(0) - 0 // 0
==> 0 - 0
==> 0
复制代码
‘-‘ 运算符执行 number 类型隐式转换对于 Date 型的值,Date.valueOf() 返回到毫秒的时间戳。
new Date(0) + 0
==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)' + 0
==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'
‘+’ 运算符触发默认转换,因此使用 toString() 方法,而不是 valueOf()。