ベストアンサー1
これを分割すると、混乱は次のようになります。
++[[]][+[]]
+
[+[]]
+[] === 0
JavaScript では、 .が何かを数値に変換するのは事実であり、この場合はまたは+
になります(以下の仕様の詳細を参照)。+""
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 は次のように評価されます。
expr を UnaryExpression の評価結果とします。
ToNumber(GetValue(expr)) を返します。
ToNumber()
言う:
物体
次の手順を適用します。
primValue を ToPrimitive(入力引数、ヒント文字列) にします。
ToString(primValue) を返します。
ToPrimitive()
言う:
物体
オブジェクトのデフォルト値を返します。オブジェクトのデフォルト値は、オプションのヒント PreferredType を渡して、オブジェクトの [[DefaultValue]] 内部メソッドを呼び出すことによって取得されます。[[DefaultValue]] 内部メソッドの動作は、8.12.8 のすべてのネイティブ ECMAScript オブジェクトに対してこの仕様で定義されています。
[[DefaultValue]]
言う:
8.12.8 [[DefaultValue]] (ヒント)
O の [[DefaultValue]] 内部メソッドがヒント文字列で呼び出されると、次の手順が実行されます。
toString を、引数 "toString" を使用してオブジェクト O の [[Get]] 内部メソッドを呼び出した結果とします。
IsCallable(toString)がtrueの場合、
a. str を、toString の [[Call]] 内部メソッドを呼び出した結果とし、O を this 値として、引数リストを空にします。
b. str がプリミティブ値の場合は、str を返します。
.toString
配列の は次のように示されます。
15.4.4.2 Array.prototype.toString()
toString メソッドが呼び出されると、次の手順が実行されます。
この値に対して ToObject を呼び出した結果を配列とします。
func を、引数 "join" を持つ配列の [[Get]] 内部メソッドを呼び出した結果とします。
IsCallable(func) が false の場合、func を標準の組み込みメソッド Object.prototype.toString (15.2.4.2) にします。
配列を this 値として、空の引数リストを指定して func の [[Call]] 内部メソッドを呼び出した結果を返します。
つまり、+[]
になります。なぜなら だからです。+""
[].join() === ""
繰り返しますが、 は+
次のように定義されます。
11.4.6 単項 + 演算子
単項 + 演算子は、そのオペランドを Number 型に変換します。
生成規則 UnaryExpression : + UnaryExpression は次のように評価されます。
expr を UnaryExpression の評価結果とします。
ToNumber(GetValue(expr)) を返します。
ToNumber
は次のように定義されます""
:
StringNumericLiteral ::: [空] のMVは0です。
したがって+"" === 0
、したがって+[] === 0
。