深入基础:[]==![]

123 阅读2分钟

  很多时候我们会碰到这样的面试题:[]==![]的值是什么,这种貌似很简单的题目往往会有个意料之外的答案。比如这道题的答案就是true,那么为什么呢,我们来分析一下。

  首先我们根据表达式规则可知,先算出![]的值,然后执行==运算符,我们知道取反运算符!的运算规则是针对值的布尔值取反,对固定六个值取反为true,其他值取反为false。这六个固定值为:""nullundefinedNaNfalse0(包括+0和-0)。所以我们可知,上面我们要算的值为false。然后我们再计算==表达式值。

使用==!=进行两个不同类型值的比较涉及到一个知识点:抽象相等比较算法。比较大致规则如下:

  • 当两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回true
  • 如果一个操作数是null,另一个操作数是undefined,则返回true
  • 如果两个操作数是不同类型的,就会尝试在比较之前将它们转换为相同类型:
    • 当数字与字符串进行比较时,会尝试将字符串转换为数字值。
    • 如果操作数之一是Boolean,则将布尔操作数 转换为1或0。
      • 如果是true,则转换为1
      • 如果是false,则转换为0
    • 如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的valueOf()toString()方法将对象转换为原始值。
  • 如果操作数具有相同的类型,则将它们进行如下比较:
    • String:true仅当两个操作数具有相同顺序的相同字符串时才返回
    • Number:true仅当两个操作数具有相同的值时才返回。+0,-0视为相同的值。如果任一操作数为 NaN,则返回false
    • Boolean:true仅当操作数为两个true或两个false时才返回true

所以跟着上面的思路,我们可以梳理出接下来转换的步骤:

  1. ![]根据运算规则得到值为布尔类型false
  2. 根据抽象相等比较算法,左边是一个对象,取其valueof值,为""
  3. 接下来是字符串与false比较,问题变成了Number("")==0,这个时候我们很容易知道最终结果为true

补充内容:
抽象相等比较算法涉及到ECMAScript规范,我们从规范中其实可以更好的看到事情的本质。

参考文档: