12月31, 2016

为什么 [ ] 是 false 而 !![ ] 是 true

今天是奇舞前端特训营 JavaScript 课程的第一天。下午的时候给学生介绍 JavaScript 的基本类型,例子中有个有趣的问题,因为时间仓促,没能详细解释。所以写一篇文章来解释,正好也考考大家:

问题:为什么 [ ] == false,而 !![ ] == true?

这是一个很有迷惑性的问题。咋一看,不可能啊?如果 [ ] == false,那么 !![ ] 相当于 !!false,难道不是为 false 吗,为什么会是 true 呢?会不会是引擎 bug,搞错了?

console.log([] == false, !![] == true); // true, true

事实上不是 bug,这与 ECMA 规范和类型转换有关。我们知道,非严格比较操作符 == 是会做强制类型转换的,那么根据 ECMA 262 它的规则是:

来源:http://www.ecma-international.org

注意一下:

  • 第 7 条:If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  • 第 9 条:If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.

所以 [] == false 的比较是对 x 执行 ToPrimitive(x),然后和 ToNumber(false) (为 0)进行比较。

看一下 ToPrimitive:

来源:http://www.ecma-international.org

来源:http://www.ecma-international.org

来源:http://www.ecma-international.org

根据上面的规则对于 ToPrimitive([ ]),先执行 [].valueOf(),返回 result 的是 [ ],因为 Type(result) 是 Object,所以继续执行 [].toString(),返回 ""

因此实际上最终是比较 "" == 0,结果为 true。

再来看 !![] == true

按照优先级,先执行 !![],根据规范,实际上是 !!(ToBoolean([]))

而 ToBoolean 的规则是:

所以 ToBoolean([]) 被转成 true,!!true 自然是 true 了。

所以这就是 [] == false!![] == true 的真正原因了。这也是为什么我们不能用 if(!array) 来判断空数组而要用 if(array.length === 0) 来判断空数组的原因。

同样,还有 [0] == false!![0] == true,现在你自己能分析出原因了。

以上就是今天的内容,如果有任何疑问,欢迎留言讨论~

本文链接:https://www.h5jun.com/post/why-false-why-true.html

-- EOF --

Comments