登录

JavaScript为什么console.log ([] == ![]) 结果为true?

javascript为什么console.log ([] == ![]) 结果为true?

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

究竟这个比的机制是怎么样的呢, 不应该是 ![]为false , 就变成了 [] == false,那么[]不应该隐式转换为true吗? 这样不就变成了 true == false 结果应该为false啊?


问题得到了本质上的解决,感谢一位朋友分享的知乎文章。原因是:
作者:Belleve
链接:https://www.zhihu.com/questio...
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

首先,== 的定义是:

GetValue 会获取一个子表达式的值(消除掉左值引用),在表达式 [] == ![] 中,[] 的结果就是一个空数组的引用,而 ![] 就有意思了,它会按照 11.4.9 和 9.2 节的要求得到 false。

比较的行为在 11.9.3 节里,所以翻到 11.9.3:

在这段算法里,和「[] == ![]」匹配的是条件 7,所以会递归地调用「[] == ToNumber(false)」进行比较。在 9.3 节中定义了 ToNumber 原语,ToNumber(false) 等于 0,于是比较变为「[] == 0」。
在此处因为 [] 是对象,比较过程走分支 9,依「ToPrimitive([]) == 0」比较。ToPrimitive 默认是调用 toString 方法的(依 8.2.8),于是 ToPrimitice([]) 等于空字符串。
结果,[] == ![] 的比较最后落到了 ''==false 上,按照 11.9.3 中的定义会依分支 5 比较 「ToNumber('')==0」,ToNumber('') 依 9.3.1 等于 0,所以结果为 true。

# JavaScript
PHPzhongPHPzhong2184 天前609 次浏览

全部回复(5) 我要回复

  • 高洛峰

    高洛峰2017-04-11 12:55:20

    var a = [],
        b = []
    console.log(a == b) // false
    var c = d = []
    console.log(c == d) //true

    []的本质是对象,作为引用值,a和b引用的地址不同

    回复
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-11 12:55:20

    先转换

    `Boolean([]) == true // 对象`
    
    [] == false  // Boolean([].toString());
    !false == true

    如果两个操作数都是对象,则比较他们是否是同一个对象,如果都指向同一个对象,则返回 true,否则返回 false
    可参考运算符
    各类判断

    回复
    0
  • 黄舟

    黄舟2017-04-11 12:55:20

    看起来知乎的答案写的有点太复杂,虽然十分标准、专业,但可能不好理解

    我在这里给出我对 == 理解

    首先,纠正一个大部人的误区

    究竟这个比的机制是怎么样的呢, 不应该是 ![]为false , 就变成了 [] == false,那么[]不应该隐式转换为true吗? 这样不就变成了 true == false 结果应该为false啊?

    == 趋向于把类型不同的指转换为 number 类型进行比较,而不是 boolean 类型

    对于

    []==![]

    先将等号右边化简

    [] == ![] 
    //=> [] == !Boolean([])
    //=> [] == !true
    //=> [] == false

    等号两边的类型不同,需要进行类型转换
    一般对象与非对象比较时,先尝试使用 valueOf 转换,再尝试使用 toString 转换

    //=> [].valueOf() == false
    //[] 的 valueOf 方法返回对象本身,仍然是一个引用值,所以尝试使用 toString 转换
    //=> [].toString() == false
    //=> ""==false

    两边类型依然不同,且都为原始值,转换为数字进行比较

    //=> Number("")==Number(false)
    //=> 0==0
    //=> true

    回复
    0
  • 巴扎黑

    巴扎黑2017-04-11 12:55:20

    console.log ([] == ![])这里会发生隐试类型转换
    []->0 ![]->false->0

    回复
    0
  • 黄舟

    黄舟2017-04-11 12:55:20

    typeof ![]
    "boolean"
    
    typeof []
    "object"
    
    [].valueOf().toString() // ""

    所有最后变成了""和false进行比较,结果为true。
    具体可以参考权威指南3.8节,大概有3到4页的篇幅详细讲这个。

    回复
    0
  • 取消回复发送