it-swarm-ja.tech

JavaScriptで2 == [2]になるのはなぜですか?

最近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?

これらの例は、jimbojw http://jimbojw.com fameと walkingeyerobot によって発見されました。

163
Xavi

ECMA-specで比較アルゴリズムを調べることができます(ECMA-262の関連セクション、問題の第3版:11.9.3、9.1、8.6.2.6)。

関連する抽象アルゴリズムを翻訳してJSに戻した場合、_2 == [2]_を評価すると何が起こるかは基本的に次のとおりです。

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

ここで、配列のvalueOf()は配列自体を返し、1要素配列の文字列表現は、単一要素の文字列表現です。

[[[[[[[2]]]]]]].toString()はストリング_2_のままであるため、3番目の例についても説明します。

ご覧のとおり、舞台裏での魔法が非常に多く含まれているため、通常は厳密な等価演算子_===_のみを使用します。

プロパティ名は常に文字列であるため、最初と2番目の例の方がわかりやすいため、

_a[[2]]
_

に等しい

_a[[2].toString()]
_

それはただ

_a["2"]
_

配列のマジックが発生する前に、数値キーでさえプロパティ名(つまり文字列)として扱われることに注意してください。

133
Christoph

これは、==演算子の暗黙的な型変換が原因です。

[2]は、数値と比較すると数値が2に変換されます。 [2]の単項+演算子を試してください。

> +[2]
2
10
Chetan Sastry
var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true

方程式の右側には、値2の数値型を返すa [2]があります。左側では、最初に2つの単一オブジェクトで新しい配列を作成しています。次に、a [(配列はここにあります)]。これが文字列と数値のどちらに評価されるかはわかりません。 2、または「2」。最初に文字列のケースを見てみましょう。 a ["2"]は新しい変数を作成し、nullを返すと信じています。 null!== 2.したがって、実際に暗黙的に数値に変換していると仮定しましょう。 a [2]は2を返します。2と2は、タイプ(つまり===が機能する)と値が一致しています。 a [value]は文字列または数値を想定しているため、暗黙的に配列を数値に変換していると思います。数値が優先されるようです。

余談ですが、誰がその優先順位を決定するのでしょうか。 [2]が最初のアイテムとして数字を持っているので、数字に変換されるからですか?または、配列をa [array]に渡すときに、配列を最初に数値に変換し、次に文字列に変換しようとします。知るか?

var a = { "abc" : 1 };
a[["abc"]] === a["abc"];

この例では、abcというメンバーを持つaというオブジェクトを作成しています。方程式の右側は非常に単純です。 a.abcと同等です。これは1を返します。左側は、最初に["abc"]のリテラル配列を作成します。次に、新しく作成された配列を渡すことにより、オブジェクトの変数を検索します。これは文字列を想定しているため、配列を文字列に変換します。これは、1と等しいa ["abc"]に評価されるようになりました。1と1は同じ型(===が機能する理由)と等しい値です。

[[[[[[[2]]]]]]] == 2; 

これは単なる暗黙的な変換です。タイプの不一致があるため、この状況では===は機能しません。

10
Shawn

==の場合、これが Doug Crockford が常に===の使用を推奨する理由です。暗黙の型変換は行いません。

===の例では、等価演算子が呼び出される前に暗黙的な型変換が行われます。

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

おもしろいです。[0]が真でも偽でもないということではありません。

[0] == true // false

Javascriptのif()演算子を処理するおもしろい方法です。

7

1つのアイテムの配列は、アイテム自体として扱うことができます。

これはアヒルのタイピングによるものです。 「2」== 2 == [2]以上である可能性があるため。

6
Ólafur Waage

他の回答に少し詳細を追加するために... ArrayNumberと比較するとき、JavascriptはArrayparseFloat(array)で変換します。コンソール(FirebugやWeb Inspectorなど)で自分で試して、どのArray値が変換されるかを確認できます。

_parseFloat([2]); // 2
parseFloat([2, 3]); // 2
parseFloat(['', 2]); // NaN
_

Arraysの場合、parseFloatArrayの最初のメンバーに対して操作を実行し、残りを破棄します。

編集:クリストフの詳細によると、内部で長いフォームを使用している可能性がありますが、結果は一貫してparseFloatと同じであるため、必ずparseFloat(array)を省略形として使用して確認できます変換方法。

3
eyelidlessness

あらゆる場合に2つのオブジェクトを比較しています。比較を考えているのであれば、==を使用しないでください。 ==多くの場合、非常識な効果が得られます。言語の良い部分を探してください:)

2
Jaseem

質問の[〜#〜] edit [〜#〜]セクションの説明:

最初の例

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

上記のクリストフの答えによると、最初に[0]をプリミティブ値にキャストし、「0」([0].valueOf().toString())を取得します。

_"0" == false
_

次に、Boolean(false)をNumberに、次にString( "0")をNumberに型キャストします

_Number("0") == Number(false)
or  0 == 0 
so, [0] == false  // true
_

ifステートメントについては、if条件自体に明示的な比較がない場合、条件はtruthyの値を評価します。

6つの偽の値のみがあります:false、null、undefined、0、NaN、空の文字列 ""。そして、偽の価値ではないものはすべて真実の価値です。

[0]は偽の値ではないため、真の値であるため、ifステートメントはtrueと評価され、ステートメントを実行します。


2番目の例

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

再び、値をプリミティブに型キャストし、

_    a = a
or  [0].valueOf().toString() == [0].valueOf().toString()
or  "0" == "0" // true; same type, same value


a == !a
or  [0].valueOf().toString() == [0].valueOf().toString()
or  "0" == !"0"
or  "0" == false
or  Number("0") == Number(false)
or  0 = 0   // true
_
0
n4m31ess_c0d3r