(![] + [])[+ []]…これが機能する理由を説明してください


107
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);

このコードの出力は次のとおりfailです。どうして?

ちなみに、(![]+[])[+!+[]] == 'false'[1]そうですね。しかし、なぜ![]+[] == "false"そしてなぜ+!+[] == 1


14
@Snoob私はあなたを信用していません。結局、それはフォーク爆弾です。
Johannes Schaub-litb 2010年

3
もちろん文字列リテラルです;)
Yi Jiang

3
(![]+[])[+[]]「F」(「偽」から最初の文字)である(![]+[])[+!+[]]等、「」である
マウリシオシェファー

3
@Snoob:あなたが言ったように、あなたはあなたのブラウザでそれぞれの式をテストすることができます。alert(![]+[])その後alert(+!+[])、試してみてください。
Mauricio Scheffer、2010年

12
役に立たないかどうかにかかわらず、私はそれを興味深い質問だと思っています。多くのコードゴルフは、有用性や実用性が考慮された場合、閉鎖されます。エクササイズとゲームは、それ自体でマインドと思考プロセスを拡張するのに役立ちます。
John K、

回答:


127

@Mauricioがコメントしたように(![]+[])[+[]]、「f」(「false」の最初の文字)、(![]+[])[+!+[]])「a」などです...

どのように機能しますか?

最初の文字「f」を見てみましょう:

(![]+[])[+[]]; // 'f'

式の最初の部分(括弧の間)はで構成され![]+[]、加算演算子の最初のオペランドはで![]ありfalse、配列オブジェクトは他のオブジェクトインスタンスと同様に真実であり、論理(!)NOT単項を適用するため、演算子、falseたとえば値を生成します。

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey

その後に、追加の2番目のオペランドである空の配列があります[]。これは、false値を文字列に変換するためだけに作成されます。

false+[]; // "false"
false+''; // "false"

最後の部分、括弧の後の角括弧のペア、それらはプロパティアクセサーであり、空の配列に再度適用された単項プラス演算子によって形成される式を受け取ります。

単項プラス演算子が行うことはNumber、たとえばへの型変換です。

typeof +"20"; // "number"

もう一度、これは空の配列に適用され、前に述べたように、配列の文字列表現は空の文字列であり、空の文字列を数値に変換すると、ゼロに変換されます。

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0

したがって、いくつかの手順で式を「デコード」できます。

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"

文字列値にブラケット表記を使用して文字にアクセスすることは、ECMAScript 3rdの一部ではないことに注意してください。エディションの仕様(それがcharAtメソッドが存在した理由です)。

ただし、文字列の文字を表すこの種の「インデックスプロパティ」はECMAScript 5で標準化されており、標準化される前でも、この機能は多くのブラウザーで使用できました(IE8(標準モード)でも)。


46
これがインタビューの質問にならないことを願っています。
2010年

4
@JTA:そうだいいのです!私は合格したでしょう:-D
Mauricio Scheffer

18
「私」はどこから来たのですか?
Josh Stodola、2010年

5
@rlemon、int言語にはデータ型はありません。実際には、すべての数値は倍精度64ビット形式(IEEE 754値)です。 。'i'この例にしていundefinedますが、それから来ることができInfinity例:(+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS

5
@JoshStodolaさて、3か月後、さらに説明します。この場合の「i」は「未定義」から来ていますが、ここには別のトリックが含まれています。このコードは、 "false"を "undefined"に連結して、 "i"のインデックスが10である"falseundefined"(を使用して構築[![]]+[][[]])を形成し+!+[]+[+[]]ます"10"。これは「i」を抽出するために使用されます(文字列インデックスは、明らかに整数に強制変換できる場合、JavaScriptで使用できます)。それを生産する最終構築物である:([![]]+[][[]])[+!+[]+[+[]]]
エントロピー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.