本质:二元操作符 + 规则
- 如果操作数是对象,则对象会转换为原始值
- 如果其中一个操作数是字符串的话,另一个操作上也会转换为字符串,进行字符串连接
- 否则,两个操作数都将转换成数字或 NaN,进行加法操作
对象转为原始数据类型的值
与下面三个方法有关,且存在优先级;首先调用第一个,第二个与第三个优先级依情况而定
- Symbol.ToPrimitive
- Object.prototype.valueOf
- Object.prototype.toString
[] 的原始值
typeof [][Symbol.ToPrimitive] // undefined,继续往下走
[].valueOf() // [],不是原始值,继续往下走
[].toString() // ''
{} 的原始值
typeof {}[Symbol.ToPrimitive] // undefined,继续往下走
({}).valueOf() // {},不是原始值,继续往下走
({}).toString() // '[object Object]'
[] + []
解题过程
- [].toString() + [].toString()
- ‘’ + ‘’
- ‘’
[] + {}
解题过程
- [].toString() + ({}).toString()
- ‘’ + ‘[object Object]’
- ‘[object Object]’
{} + [],易错
想当然的解题过程:
- ({}).toString() + [].toString()
- ‘[object Object]’ + ‘’
- ‘[object Object]’
可以在浏览器试一下,其实结果是 0
因为浏览器把 {} + []
解析成这样了 {}; + []
,也就是一个语句后面跟了一个 +[]
,+[]
相当于 + ''
,结果为 0
{} + {},易错
想当然的解题过程:
- 语句后面跟上
+{}
+ '[object Object]'
- NaN
那么答案是 NaN
吗?
对了,又没有完全对。{} + {}
在 IE 或 FireFox 等浏览器上的执行结果确实为 NaN
,但是在 Chrome 浏览器上执行结果为 '[object Object][object Object]'
Chrome 浏览器会对这段代码进行特殊处理,处理后为 ({} + {})
那么解题过程就为:
- (({}).toString() + ({}).toString())
- ‘[object Object][object Object]’