为什么 2 == [2] 在 JavaScript 中?

2022-08-30 02:03:39

我最近在JavaScript中发现了这一点。事实证明,这个怪癖有几个有趣的后果:2 == [2]

var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true

同样,以下方法有效:

var a = { "abc" : 1 };
a[["abc"]] === a["abc"]; // this is also true

更奇怪的是,这也有效:

[[[[[[[2]]]]]]] == 2; // this is true too! WTF?

这些行为在所有浏览器中似乎都是一致的。

任何想法为什么这是一个语言功能?

以下是此“功能”的更疯狂的后果:

[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!

var a = [0];
a == a // true
a == !a // also true, WTF?

答案 1

您可以在 ECMA 规范中查找比较算法(ECMA-262 的相关部分,您的问题的第 3 版:11.9.3、9.1、8.6.2.6)。

如果你将所涉及的抽象算法转换回JS,那么在评估时发生的事情基本上是这样的:2 == [2]

2 === Number([2].valueOf().toString())

其中 for 数组返回数组本身,一元素数组的字符串表示形式是单个元素的字符串表示形式。valueOf()

这也解释了第三个例子,因为它仍然只是字符串。[[[[[[[2]]]]]]].toString()2

如您所见,涉及相当多的幕后魔术,这就是为什么我通常只使用严格的相等运算符 。===

第一个和第二个示例更容易理解,因为属性名称始终是字符串,因此

a[[2]]

等效于

a[[2].toString()]

这只是

a["2"]

请记住,在任何数组魔术发生之前,即使是数字键也会被视为属性名称(即字符串)。


答案 2

这是因为运算符的隐式类型转换。==

[2] 与数字相比,转换为数字为 2。尝试 [2] 上的一元运算符。+

> +[2]
2