1. ホーム
  2. javascript

[解決済み] なぜ ++[[]][+[] +[+[]] は "10" という文字列を返すのでしょうか?

2022-03-19 09:23:10

質問

これは有効で、文字列 "10" をJavaScriptで作成した場合( その他の例はこちら ):

console.log(++[[]][+[]]+[+[]])

なぜ?ここで何が起こっているのでしょうか?

どうすればいい?

分割すれば、ごちゃごちゃはイコールになる。

++[[]][+[]]
+
[+[]]

JavaScriptでは +[] === 0 . + は何かを数値に変換しますが、この場合、次のようになります。 +"" または 0 (後述する仕様の詳細参照)。

したがって、単純化することができます( ++ が優先されます。 + ):

++[[]][0]
+
[0]

なぜなら [[]][0] の最初の要素を取得するという意味です。 [[]] , というのは本当です。

[[]][0] は、内側の配列( [] ). リファレンスの関係で、以下のように言うのは間違いです。 [[]][0] === [] という配列がありますが、内側の配列を A というように、間違った表記を避けるためです。

++ をオペランドの前に置くと、「1つインクリメントして、インクリメントした結果を返す」ことを意味します。つまり ++[[]][0] は、次のように等価です。 Number(A) + 1 (または +A + 1 ).

ここでも、ごちゃごちゃしたものをもっと読みやすいものに単純化することができます。ここでは [] に戻る。 A :

(+[] + 1)
+
[0]

+[] は、配列を数値に変換することができます。 0 の場合、最初に文字列に変換する必要があります。 "" を、もう一度。最後に 1 が追加され、その結果 1 .

  • (+[] + 1) === (+"" + 1)
  • (+"" + 1) === (0 + 1)
  • (0 + 1) === 1

さらに簡略化してみましょう。

1
+
[0]

また、これはJavaScriptでも同じです。 [0] == "0" というのは、1つの要素で配列を結合しているからです。で区切られた要素を結合することになります。 , . 要素が1つであれば、このロジックは最初の要素そのものになることが推論できます。

この場合 + は 2 つのオペランド、つまり数値と配列を受け取ります。この2つのオペランドを同じ型に変換しようとしているのです。まず、配列は文字列に変換されます。 "0" 次に、数値は文字列( "1" ). 番号 + 文字列 === 文字列 .

"1" + "0" === "10" // Yay!


の仕様詳細 +[] :

これはかなり迷路ですが、行うには +[] ということで、まず文字列に変換されます。 + と言っています。

<ブロッククオート

11.4.6 単項+演算子

単項演算子 + は、オペランドを Number 型に変換します。

プロダクションの UnaryExpression : + UnaryExpression は,次のように評価される。

  1. UnaryExpressionの評価結果をexprとする。

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

ToNumber() は言う。

対象物

以下の手順を適用してください。

  1. primValueをToPrimitive(input argument, hint String)とする。

  2. ToString(primValue)を返します。

ToPrimitive() は言う。

対象物

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

[[DefaultValue]] は言う。

8.12.8 [[デフォルト値]]について (ヒント)

O の内部メソッド[[DefaultValue]]がヒント String で呼び出されたとき。

  1. オブジェクトOの[[Get]]内部メソッドを引数"toString"で呼び出した結果をtoStringとする。

  2. IsCallable(toString)が真であれば。

a. toStringの内部メソッド[[Call]]を、Oをこの値として、引数リストを空にして呼び出した結果をstrとする。

b. strがプリミティブ値であればstrを返す。

.toString という配列の

15.4.4.2 Array.prototype.toString ( )

toStringメソッドが呼ばれると、次のような手順で処理されます。

  1. この値に対してToObjectを呼び出した結果をarrayとする。

  2. 引数 "join" を指定して配列の [[Get]] 内部メソッドを呼び出した結果を func とします。

  3. IsCallable(func) が false ならば、func は標準的な組み込みメソッド Object.prototype.toString (15.2.4.2) であるとする。

  4. funcの内部メソッド[[Call]]にarrayをこの値として与え、空の引数リストを呼び出した結果を返します。

そこで +[] になります。 +"" というのも [].join() === "" .

ここでも + は次のように定義されます。

11.4.6 単項+演算子

単項演算子 + は、オペランドを Number 型に変換します。

プロダクションの UnaryExpression : + UnaryExpression は,次のように評価される。

  1. UnaryExpressionの評価結果をexprとする。

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

ToNumber は、以下のように定義されています。 "" としています。

StringNumericLiteral :: のMVです。[empty]は0です。

そこで +"" === 0 というように +[] === 0 .