1. ホーム
  2. javascript

[解決済み] (![]+[])[+[]]... なぜそうなるのか、説明してください。

2022-09-05 08:27:29

質問

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

このコードの出力は fail . なぜ?

どのように解決するのですか?

Mauricio さんのコメントにもあるように (![]+[])[+[]] は "f" ("false" の1文字目) です。 (![]+[])[+!+[]]) は "a"である、など。

どのように動作するのですか?

1文字目の'f'を調べてみましょう。

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

式の最初の部分(括弧で囲まれた部分)は、以下のように構成されています。 ![]+[] であり、Addition 演算子の最初のオペランドは ![] であり、これは false 配列オブジェクトは他の Object インスタンスと同じように 真実である であり、論理演算子(!)NOT を適用すると false を生成します。

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

この後、加算の2番目のオペランドである空のArrayがあります。 [] を変換するために作られたものです。 false の値を String に変換しています。空の配列の文字列表現はただの空の文字列なので、これと同じです。

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

最後の部分、括弧の後の角括弧のペアはプロパティアクセサであり、空の配列に再び単項演算子を適用した式を受け取ります。

単項演算子が行うのは型変換であり、次のようになります。 Number などに変換します。

typeof +"20"; // "number"

もう一回、これは空のArrayに適用されます。先ほど言ったように、ArrayのString表現は空の文字列であり、空の文字列をNumberに変換すると0に変換されます。

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

したがって、いくつかのステップで、式を "decode"することができます。

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

String 値にブラケット記法を用いて文字にアクセスすることは、ECMAScript 3rd. Edition 仕様には含まれていないことに注意してください (そのため charAt メソッドが存在したのはそのためです)。

しかし、このような文字列の文字を表す "index properties" は ECMAScript 5 で標準化され、標準化以前からかなりの数のブラウザで(IE8(標準モード)でも)この機能が利用可能でした。