『前端碎碎念』系列会记录我平时看书或者看文章遇到的问题,一般都是比较基础但是容易遗忘的知识点,你也可能会在面试中碰到。 我会查阅一些资料并可能加上自己的理解,来记录这些问题。更多文章请前往我的个人博客
这道题跟之前提到的[] == ![]
有异曲同工之妙,都是涉及到了隐式的强制类型转换。同样,我们直接开门见山,总结下加号操作符的运算规则。下面规则判断权重由上往下。
-
当 两个操作数都是数值 时,执行常规的数值加法计算。但有几个值的考虑
如果有一个操作数是NaN, 则结果是NaN;
Infinity 加 Infinity 结果是 Infinity;
-Infinity 加 -Infinity 结果是 -Infinity;
Infinity 加 -Infinity 结果是NaN;
+0 加 +0 结果是+0;
-0 加 -0 结果是 -0;
+0 加 -0 结果是+0;
-
当有 一个操作数是字符串 时,应用如下规则:
如果两个操作数都是字符串,则将两个字符串拼接起来;
如果只有一个操作符是字符串,则两另一个操作符转换为字符串(toString),然后再将两个字符串拼接起来。
前面两条规则都非常简单,不会有混淆。对于其他情况,我总结了下面两条规则:
当 有一个操作数是复杂数据类型(对象,数组) 时,将两个操作数都转换为字符串(ToString)相加。
当 有一个操作数是简单数据类型(true/false, null,undefined) 时,同时不存在复杂数据类型和字符串,则将两个操作数都转换成数值(ToNumber)相加。
另外还有一种特殊情况{} + 头 的相加式,有些浏览器会将{}视为一个块符号,所以不会参与相加,而是把+符号视为转换符(Number)将后面的操作数转换为数值。
注意上面的规则的权重是从上到下的,每执行一步要从第一条规则开始再进行判断。
下面是改规则的一个判断流程图:
我们来看看这几道题
1.[] + {}
根据规则,[] 和 {} 都是复杂数据类型,满足有一个操作符是复杂数据类型, 所以将两个值都转换为字符串,调用其toString方法,得到:
"" + "[object Object]" = "[object Object]"
2.1+{}
同样满足第三条规则,结果为
"1" + "[object Object]" = "1[object Object]"
3.'1' + false
其中false满足第4条规则,但同时满足第2条规则'1'是字符串,优先处理第2条规则。所以处理结果应该是将false转为字符串
"1" + "false" = "1false"
看看题目中的 {} + []
按规则计算结果应该是"[object Object]"
但是控制台打印出来的结果却是0
,别忘了第5条,当{}+开头的时候,{}并不参与计算,只是被单做一个空的代码块,所以{}+[]
实际上是+[]
, 即Number([]) => Number("") => 0
那么{}+{}
就是+{}
,等于Number({}) => Number("[object Object]") => NaN
然而我们看到结果再次出乎我们的意料,控制台输出的是"[object Object][object Object]"
到底是怎么回事?
原来对于{}+{}
不同浏览器会有不同的处理结果,在chrome中会输出"[object Object][object Object]"
,在firefox会输出NaN
。
这应该是不同浏览器的js引擎解析差异引起的。我们只要记住这个特殊情况就行了。
其实这些特殊值的计算我们平时都很少接触到,也没有多大的意义。关键还是要加深对JS中对数值转换的理解,以不变应万变。到真正遇到问题的时候,不至于摸不着头脑。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。