如果 [0] == 0 和 0 == [[0]] 都为真,则为什么 [0] == [[0]] 为假

If both [0] == 0 and 0 == [[0]] are true than why is [0] == [[0]] false?

本文关键字:为什么 为假 如果      更新时间:2023-09-26

我们都知道javascript在测试相等性时会进行时髦的转换,但是在引擎盖下究竟发生了什么?

> [0] == 0
true
> 0 == [[0]]
true
> [0] == [[0]]
false

是的,我天真地期望 == 运算符的传递性。

[0] == 00 == [[0]]将基元值与对象进行比较,因此将执行类型转换。在这两种情况下,[0][[0]] 最终都将转换为基元值 0

这是在抽象相等比较算法的步骤 8(和 9)中定义的:

  1. 如果 Type(x) 是字符串或数字,Type(y) 是对象,
    返回比较结果 x == ToPrimitive(y)。

但是,[0] === [[0]]比较两个对象,并且两个不同的对象永远不会相等:

1f. 如果 xy 引用同一对象,则返回 true。否则,返回 false。


下面是一个稍微简单的例子,它证明了松散比较不是传递的:

" " == 0 // true
"'n" == 0 // true
" " == "'n" // false

前两个比较执行类型转换(字符串到数字),最后一个不执行,两个字符串的值不同。

您的前 2 个示例隐式地将数组转换为字符串,然后将其与0进行比较:

var a = [0].toString(); // "0"
var b = a == 0 // "0" == 0; // true

最后一个示例不强制转换数组,它只是比较数组的标识。显然,这些不匹配,因此返回false

在您的示例中,您在其中一些数组中拥有的额外深度层不会产生任何影响:

[0] == [0]     // false, they're not the same array.
0 == [[[[0]]]] // true, [[[[0]]]].toString() === "0", "0" == 0

正如@JanDvorak在对@KooiInc答案的评论中提到的,在幕后,JS不使用toString进行此转换。然而,从概念上讲,这就是正在发生的事情。

行为符合 JavaScript 抽象相等比较算法

  1. 比较 [0] == 0 - 操作数类型不同

匹配算法的情况 9:Type(x) 是对象,Type(y) 是字符串 或数字
结果: ToPrimitive(x) == y. 即 '0' == 0, 因此为 true

  1. 比较 0 == [[0]] - 操作数类型不同

匹配算法的大小写 8:如果 Type(x) 是字符串或数字,而 Type(y) 是对象, 结果: x == 到基元(y)。即 0 == '0',因此为真

  1. 比较 [0] == [[0]] - 操作数类型相同,即对象

匹配算法的情况 1:类型(x) 与类型(y) 相同, 如果类型为"对象" 如果 x 和 y 引用同一对象,则返回 true。否则,返回 false。 即引用将被匹配,因此为 false