花五分钟Get[]+[]、[]+{}、{}+[]、{}+{}背后的玄机👌

84 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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。