8

説明できない実用的なJavaScriptコードに出くわしました。例えば:

  • +[]===0
  • -[]===0
  • ~[]===-1
  • ~-~[]===-2
  • ~-~-~-~-~[]===-5
  • ~-~-~-~-~[]+~[]===-6
  • ~+~[]===0
  • ~+~+~[]===-1
  • ~+~+~+~[]===0

これらの表現の論理を説明できますか?

4

5 に答える 5

11

[]は空の配列オブジェクトなので、次のようになります。

+[]: 空の配列を強制的に正の整数、つまり 0、つまり === から 0 にする
-[]: 空の配列を強制的に負の整数、つまり 0、つまり === から 0 にする
~[]: ビット単位の NOT -1 に評価される空の配列、つまり === から -1
~-~[]: 否定された NOT 化された空配列のビット単位の NOT:~-(-1) -> ~1 -> -2

等...

于 2011-11-23T17:23:44.507 に答える
2

何かに+or演算子を使用すると、それが呼び出されます。を返すので、最初の 2 つの答えが得られます。-NumberNumber([])0

~演算子はビット単位のNOT です。基本的に、数値のすべてのビットを反転し、 に変更0-1ます。ビット演算子の詳細については、こちらを参照してください。

残りは、これらのケースの単なる組み合わせです。これらを組み合わせて、好きな数を作ることができます。

于 2011-11-23T17:25:16.720 に答える
2

質問で示した結果を言い直すのではなく、その結果が得られた理由を説明しようと思います。

説明

最初の例だけを取り上げて (残りは同様のことを行うため)、仕様に従って何が起こるかを確認できます。

11.4.6 Unary + Operatorから、ToNumber変換が行われていることがわかります。

ToNumber(GetValue(expr)) を返します。

9.3 ToNumberから、オブジェクト (配列など) が与えられた場合、ToPrimitive変換が行われた後にToNumber.

物体

次の手順を適用します。

  1. primValue を ToPrimitive(入力引数、ヒント番号) とします。
  2. ToNumber(primValue) を返します。

9.1 から Primitiveまで、オブジェクトを取得すると、そのオブジェクトがフェッチされToPrimitiveていることがわかります。[[DefaultValue]]

物体

オブジェクトのデフォルト値を返します。オブジェクトのデフォルト値は、オブジェクトの [[DefaultValue]] 内部メソッドを呼び出し、オプションのヒント PreferredType を渡すことによって取得されます。[[DefaultValue]] 内部メソッドの動作は、8.12.8 のすべてのネイティブ ECMAScript オブジェクトについて、この仕様によって定義されています。

8.12.8 [[DefaultValue]] (ヒント)から、最終的に起こることはtoString()、配列で呼び出されて返されることです。ToNumberこの文字列は、上記のように再帰的に送信されます。

ToNumberでは、文字列に対して変換が行われるとどうなるでしょうか? それは9.3.1 ToNumber Applied to the String Typeで説明されており、少し長くなっています。より簡単なのは、変換を直接実行して、何が起こるかを確認することです。

Number("");     // result is 0 on an empty string
Number("    "); // result is 0 on a string with only whitespace
Number("123");  // result is 123 on a numeric string
Number(" 123 ");// result is 123 on a numeric string with leading & trailing spaces
Number("abc");  // result is NaN (not a number) on non-numeric strings

問題は、配列からどの文字列を取得するかです。繰り返しますが、これは簡単にテストできます。

[].toString();  // result is "" (empty string)

結果は空の文字列であり、空の文字列のToNumber変換は0上記のとおりであるため、比較していることになります0 === 0

次のようにした場合と同じです。

Number( [].toString() ) === 0; // true

または、もう少し引き出すには:

var x = [];
x = x.toString();  // ""
x = Number( x );   // 0
x === 0;  // true

より多くのtoString結果。

toString配列の変換をさらに表示するには、次のことを考慮してください。

[1].toString();            // "1"
[1,2,3].toString();        // "1,2,3"
["a",1,"b",2].toString();  // "a,1,b,2"

したがってToNumber、上記の配列で変換を行うと、最初の配列は数値になり、最後の 2 つは になりNaNます。

Number([1]);            // 1
Number([1,2,3]);        // NaN
Number(["a",1,"b",2]);  // NaN

いくつかの証拠

このtoString()変換が変換の前に行われることをさらに証明するために、ToNumber実際に変更Array.prototype.toStringして別の結果を提供することができ、ToNumber変換はその変更された結果を使用します。

Array.prototype.toString = function() {
    var n = 0;
    for( var i = 0; i < this.length; i++ ) {
        n += this[i];
    }
    return n;
};

toStringここでは、 onArray.prototypeを配列を合計する関数に置き換えました。明らかに、これを行いたくないのですが、どのように異なる結果が得られるかを示すことができます。

Number([1,2,3]);   // 6
+[1,2,3];          // 6

ToNumberこれで、以前は結果だった配列の変換が、配列NaN内の項目の合計になっていることがわかります。

于 2011-11-23T19:45:29.400 に答える
1

私は自分のベストを尽くします:

[]===0[]は0と正確に等しくないため、もちろんfalseです。ただし、[]==0暗黙のキャストが存在するため、trueです。

+-[]プラスまたはマイナスが[]実数にキャストされるため、機能します。

~0(0のビット単位の逆数)は-1です。したがって、~[]===-1動作します。

他のものは、-1を何回も減算または加算するだけで機能します。

于 2011-11-23T17:27:18.767 に答える
0

私が間違っている場合は修正してください。ただし、配列に追加する (配列に値を追加するのではなく、配列に値を追加するなど) と、数値にキャストされます。残りは、基本的な +, - 演算子 (チルダ (~) はビットごとの NOT です) を使用して数値を変更し、次に方程式を変更するだけです。

So [] == array ([]);
[] + 1 == number (0);
+[]===0 (true)
于 2011-11-23T17:26:08.473 に答える