最近比较频繁的碰见 JavaScript 类型转换的问题:
00const res1 = [] + {}; 01// => '[object Object]' 02 03const res2 = {} + []; 04// => '[object Object]' 05 06const res3 = eval('{} + []'); 07// => 0 08 09console.log(res1); 10console.log(res2); 11console.log(res3);
# res1 ↵
- 计算 [] + {} 的时候,先要转换 [] 为原始类型,那该怎么转换呢,看加数的类型。
- 加数是对象,调用它的 valueOf, 结果还是对象,最后调用 toString() 得 ‘[object Object]’
- 之后计算 [] + ‘[object Object]’
- [] 调用 valueOf 得到它自己,然后调用 toString 得到空字符串,所以最终答案是 ‘[object Object]’
# res2 ↵
没什么特别的,跟上面一样。
# res3 ↵
{} 被解释为代码快,源代码等价于:
00console.log( 01 // 打印一下这个表达式的最终结果 02 +[] 03);
其实就是
+[]
答案是 0,为啥呢,因为 [].valueOf 是它自己,然后调用 toString 是空字符串,最后得到 (+"")
,等价于 Number("")
得到 0# valueOf、toString 优先级 ↵
valueOf toString 的优先级可以通过几个例子说明:
00console.log( 01 // string + object 02 ('20' + { 03 valueOf: () => 2, 04 toString: () => '20' 05 }) 06); 07// => '202' 08 09console.log( 10 // object + string 11 ({ 12 valueOf: () => 2, 13 toString: () => '20' 14 } + '20') 15); 16// => '220' 17 18console.log( 19 // object + object 20 ({ 21 valueOf: () => 1, 22 toString: () => '10' 23 } + { 24 valueOf: () => 2, 25 toString: () => '20' 26 }) 27); 28// => 3
说明无论什么情况下,优先调用 valueOf,其次才是 toString,其调用顺序是操作数无关的,也就是说被加数或者加数是啥类型它不会管。
# jsfuck ↵
http://www.jsfuck.com/