持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
在进行[]+[]、[]+{}、{}+[]、{}+{}计算时本质是发生了复杂数据类型转为原始数据类型的值。
在复杂数据类型转为原始数据类型的值时,有三个方法与此有关:
- Symbol.ToPrimitive
- Object.prototype.valueOf
- Object.prototype.toString
在发生转化时,会先调用Symbol.ToPrimitive(如果存在的话),第二个方法与第三个方法视情况而定,如果调用它俩其中一个返回的不是原始值那么会调用下一个。
[]的原始值
console.log(typeof [][Symbol.toPrimitive]); // undefined
console.log([].valueOf()); // []
console.log([].toString()); // ''
可见[]上不存在Symbol.toPrimitive方法、[]的valueOf方法返回的依旧是[]而不是原始值、[]的toString方法返回的是空字符串。
所以,[]的原始值为空字符串。
{}的原始值
console.log(typeof {}[Symbol.toPrimitive]); // undefined
console.log({}.valueOf()); // {}
console.log({}.toString()); // '[object Object]'
可见{}上不存在Symbol.toPrimitive方法、{}的valueOf方法返回的依旧是{}而不是原始值、{}的toString方法返回的是字符串'[object Object]'。
所以,{}的原始值为字符串:'[object Object]'
[] + []
由于[]+[]时相当于 [].toString() +[].toString() 。
所以[]+[]相当于 ''+'' ,最后结果是空字符串。
console.log([] + []); // ''
[] + {}
由于[]+{}时相当于 [].toString()+{}.toString() 。
所以[]+{}相当于 ''+'[object Object]' ,最后结果是'[object Object]'。
console.log([] + {}); // '[object Object]'
{} + []
{} + []比较特殊,如果在编辑器中,会得到与[]+{}相同的结果:'[object Object]'。
console.log({} + []); // '[object Object]'
但是如果在浏览器的控制台中计算,会得到0,这是为什么呢?
这是因为会将{}当成“语句”,所以相当于只是执行了+[]的操作,由于[]的原始值是空字符串,所以+''时相当于执行了Number('') ,最终结果为0。
{} + {}
在Chrome浏览器与编辑器中{}+{}会得到'[object Object][object Object]',因为{}的原始值为'[object Object]',所以相当于两个字符串进行了拼接。
console.log({} + {}); // '[object Object][object Object]'
在Chrome浏览器
的控制台上运行{}+{},相当于 ({} + {}) 所以不会将{}当成语句。
但是在FireFox与IE浏览器
的控制台上运行,结果为NaN。
这是因为在FireFox与IE浏览器中会将{}+{}的第一个{}看成语句,也就是说最后执行相当于 + '[object Object]',即Number('[object Object]'),所以最后结果为NaN。