2011-11-23 17 views
8

説明できないJavaScriptコードが出てきました。例えば :〜[]構築はどのようにJavaScriptで動作しますか?

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

あなたは、これらの式のロジックを説明できますか?

+ []:

+2

私はそのようなコードに遭遇すれば私は机を裏返すだろうと思う。 –

+1

答えは:+ [NaN] == !!!! 0 && + [{}] + ~~ [[]] - [] ' – jAndy

+1

私はどのコードベースでも、元の開発者にリライトそれ。それはひどい練習です! –

答えて

11

[]ので、空の配列オブジェクトである力空の配列は0
に===は正の整数、別名0であるように[ - ]:力空の配列になるように負の整数、別名0 = 0から0まで
〜[]:-1で-1と評価されるビット単位でない空の配列
〜〜[]:否定のビット単位NOT空の配列NOTFT:~-(-1) -> ~1 -> -2

など...

+1

は、最後の文字列の '〜1 - > -2'にする必要があります。 – Denis

+0

ありがとう、答えを修正しました。 –

+0

-1 '+ []:空の配列を強制的に正の整数にする、別名0、===〜0'はなぜそれが起こるのか説明しません。それは単に結果を再表示します。明らかに '+ [] === 0'なら、' + [] 'は' 0'に変換されていなければなりません。質問は論理を説明するよう求めます。 – RightSaidFred

2

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

~演算子はビット単位ではありません。基本的には数字のすべてのビットを反転し、0から-1に変更します。ビット単位の演算子に関する詳細here

残りは、これらのケースの組み合わせです。あなたは、あなたが望む任意の数を作るためにそれらのものをかなり組み合わせることができます。

+0

入手しました。私は '[] 'から' 0 '部分へのキャスティングを見逃しました。 – Denis

0

私が間違っていると私は正しいと思っていますが、配列に値を追加するのではなく、値を配列に追加すると、数値にキャストされます。残りの部分は基本+、 - 演算子(チルダ(〜)はビット単位でNOT)を使用して数を変更してから方程式を修正します。

So [] == array ([]); 
[] + 1 == number (0); 
+[]===0 (true) 
+0

実際には数値ではなく文字列にキャストします。 '[1] + 1 =" 11 "' so '+ [] = 0'は' + " – pleasedontbelong

1

私は自分のベストを尽くします:暗黙のキャストが存在するため

[]===0は、偽のはもちろんである[]しかし0に正確に等しいではないので、[]==0は本当です。

+および-[]は、プラスまたはマイナスキャスト[]を実数にキャストします。

~0(ビット反転が0)は-1です。したがって~[]===-1が機能します。

他は、-1を複数回減算または加算するだけで動作します。

2

あなたが質問で示した結果を単に書き直す代わりに、私はなぜの結果を得るのかを説明しようとします。

説明

(残りは似たようなことを行いますので)最初の例に取ると、私たちは何が起こるかを見るために仕様に従うことができます。

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

Return ToNumber(GetValue(expr))。私たちは(あなたのアレイのような)オブジェクトを指定した場合、ToPrimitive変換はToNumberで別の試みに続いて行われていることがわかり9.3 ToNumberから

オブジェクトは、次の手順を適用します。

  1. がprimValueがたToPrimitive(入力引数、ヒント番号)とします。
  2. Return ToNumber(primValue)。 ToPrimitiveは、オブジェクトを取得する場合9.1 To Primitiveから

、我々はその[[DefaultValue]]がフェッチであることがわかります。

オブジェクト

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

8.12.8 [[DefaultValue]] (hint)から、最終的には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結果を。

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

ので、上記アレイ上ToNumber変換を行うために最初は私たちに番号を与えるだろう、最後の2つのことになる:、配列のよりtoString変換を示し、次のことを考慮すること

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; 
}; 

私は、Arrayを合計する機能をArray.prototypetoStringを交換しました。明らかにこれをやりたくはありませんが、私たちは今どのように違う結果が得られるかを示すことができます。

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

だから今は、以前NaNに生じるであろう私たちのアレイのToNumber変換は今や配列内のアイテムの合計が生じていることがわかります。

関連する問題