1. ホーム
  2. javascript

[解決済み] JavaScriptで2 == [2]になるのはなぜですか?

2022-04-23 13:58:51

質問

最近発見したのですが 2 == [2] をJavaScriptで作成しました。 結論から言うと、この癖はいくつかの興味深い結果をもたらします。

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?

解決方法は?

ECMA-spec で比較アルゴリズムを調べることができます(ECMA-262, 3rd edition の該当セクション:11.9.3, 9.1, 8.6.2.6).

もし、関係する抽象的なアルゴリズムをJSに翻訳し直した場合、次のようなことが起こります。 2 == [2] は基本的にこうです。

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

ここで valueOf() は配列そのものを返し、1要素配列の文字列表現はその1要素の文字列表現を返します。

これは、3番目の例も次のように説明します。 [[[[[[[2]]]]]]].toString() は、やはり単なる文字列 2 .

ご覧のように、舞台裏ではたくさんのマジックが行われています。そのため、私は一般的に厳密な等号演算子である === .

最初の例と2番目の例は、プロパティ名が常に文字列であるため、より簡単です。

a[[2]]

は、以下と同等です。

a[[2].toString()]

であり、これは単に

a["2"]

数値キーも、配列の魔法がかかる前にプロパティ名 (つまり文字列) として扱われることを覚えておいてください。