2

『前端碎碎念』系列会记录我平时看书或者看文章遇到的问题,一般都是比较基础但是容易遗忘的知识点,你也可能会在面试中碰到。 我会查阅一些资料并可能加上自己的理解,来记录这些问题。更多文章请前往我的个人博客

这道题跟之前提到的[] == ![] 有异曲同工之妙,都是涉及到了隐式的强制类型转换。同样,我们直接开门见山,总结下加号操作符的运算规则。下面规则判断权重由上往下。

  1. 两个操作数都是数值 时,执行常规的数值加法计算。但有几个值的考虑

    • 如果有一个操作数是NaN, 则结果是NaN;

    • Infinity 加 Infinity 结果是 Infinity;

    • -Infinity 加 -Infinity 结果是 -Infinity;

    • Infinity 加 -Infinity 结果是NaN;

    • +0 加 +0 结果是+0;

    • -0 加 -0 结果是 -0;

    • +0 加 -0 结果是+0;

  2. 当有 一个操作数是字符串 时,应用如下规则:

    • 如果两个操作数都是字符串,则将两个字符串拼接起来;

    • 如果只有一个操作符是字符串,则两另一个操作符转换为字符串(toString),然后再将两个字符串拼接起来。

前面两条规则都非常简单,不会有混淆。对于其他情况,我总结了下面两条规则:

  1. 有一个操作数是复杂数据类型(对象,数组) 时,将两个操作数都转换为字符串(ToString)相加。

  2. 有一个操作数是简单数据类型(true/false, null,undefined) 时,同时不存在复杂数据类型和字符串,则将两个操作数都转换成数值(ToNumber)相加。

  3. 另外还有一种特殊情况{} + 头 的相加式,有些浏览器会将{}视为一个块符号,所以不会参与相加,而是把+符号视为转换符(Number)将后面的操作数转换为数值。

注意上面的规则的权重是从上到下的,每执行一步要从第一条规则开始再进行判断。

下面是改规则的一个判断流程图:

roadmap.path

我们来看看这几道题

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中对数值转换的理解,以不变应万变。到真正遇到问题的时候,不至于摸不着头脑。


fwon
2.5k 声望259 粉丝