前几天在朋友圈看到看到一个JavaScript中对象和数组“+”运算的问题,发现自己不能完全理解里面的答案,来查漏补缺一下。
- TOC
{:toc}
Question:
问题包含四个:
- [] + [] = ?
- [] + {} = ?
- {} + [] = ?
- {} + {} = ?
chrome下表现
- [] + [] = “”
- [] + {} = “{object Object}”
- {} + [] = 0
- {} + {} = “{object Object}{object Object}”
FF 下表现
- [] + [] = “”
- [] + {} = “{object Object}”
- {} + [] = 0
- {} + {} = NaN
Node 下表现
与 chrome表现一致
ECMA中对“+”的描述:
参考了 ecma 中对 getValue
的描述,里面有一句 then let get be the [[Get]] internal method of base
看得不太懂,找不到get
这个函数变量是哪来的,不过在这个场景下,我们可以判断[]和{}调用 getValue 返回的结果分别是 []和{}。
接下来到 getPrimitive
方法, ECMA中的描述:
另外在网上找到了一个小诀窍:当+作用在一个是数字一个是字符串的情况下,+作为连接运算符。
分析:
使用+运算符进行运算时,是没有指定转换方式的,JavaScript 内部会默认进行 toNumber 转换。(划重点)
[] + []
[]调用 valueOf 返回 [],不是原始值,调用 toString,返回””,为原始值。因此结果是”” + “” = “”。
[] + {}
{}调用 valueOf 返回 {},不是原始值,调用 toString,返回”{object Object}”。因此结果是”” + “{object Object}” = “{object Object}”。
第三和第四个是以 {
开始的,情况比较特殊,在 Chrome 和 FF 下的表现也不一致。
{} + []
当一个语句以
{
开始时,浏览器会认为它是一个语句块,知道匹配到一个}
。 因此这个返回值实际上是后面+[]
的结果,这是一个单值运算,隐式转化调用toNumber。toNumber 会先调用 getPrimitive 取到[]的原始值为””,然后将””转换为数字————0。如果不想{}被默认为代码块,可以通过添加
()
。({} + [] = “{object Object}”){} + {}
这个运算个人感觉Chrome 的实现是有问题的,它的逻辑和第三点矛盾了,而 FF 的结果才是正确的。这个实际上是 +{} 的运算结果。toNumber 把 {}的原始值 “{object Object}” 转换成数值时是 NaN,很正确,没毛病~
后话
感觉自己的前端基础还是很一般,js有很多内部的逻辑都没弄清楚,上班后更是懒了很少学习新东西,真的很怀念以前在学校做项目,菜鸟一只每次学习到新东西很兴奋的时光。
ECMA的官方文档是个好东西,最权威,最透彻,虽然英文看起来有点痛苦。
给自己打下气,知道现在学习前端还是使我很愉♂悦的~望能坚持下去。