[解決済み] なぜ ++[[]][+[] +[+[]] は "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 は,次のように評価される。
-
UnaryExpressionの評価結果をexprとする。
-
ToNumber(GetValue(expr))を返します。
ToNumber()
は言う。
対象物
以下の手順を適用してください。
primValueをToPrimitive(input argument, hint String)とする。
ToString(primValue)を返します。
ToPrimitive()
は言う。
対象物
Objectのデフォルト値を返します。オブジェクトのデフォルト値は、オブジェクトの [[DefaultValue]] 内部メソッドを呼び出し、オプションのヒント PreferredType を渡すことによって取得されます。DefaultValue]]内部メソッドの動作は、8.12.8ですべてのネイティブECMAScriptオブジェクトのためにこの仕様で定義されています。
[[DefaultValue]]
は言う。
8.12.8 [[デフォルト値]]について (ヒント)
O の内部メソッド[[DefaultValue]]がヒント String で呼び出されたとき。
オブジェクトOの[[Get]]内部メソッドを引数"toString"で呼び出した結果をtoStringとする。
IsCallable(toString)が真であれば。
a. toStringの内部メソッド[[Call]]を、Oをこの値として、引数リストを空にして呼び出した結果をstrとする。
b. strがプリミティブ値であればstrを返す。
は
.toString
という配列の
15.4.4.2 Array.prototype.toString ( )
toStringメソッドが呼ばれると、次のような手順で処理されます。
この値に対してToObjectを呼び出した結果をarrayとする。
引数 "join" を指定して配列の [[Get]] 内部メソッドを呼び出した結果を func とします。
IsCallable(func) が false ならば、func は標準的な組み込みメソッド Object.prototype.toString (15.2.4.2) であるとする。
funcの内部メソッド[[Call]]にarrayをこの値として与え、空の引数リストを呼び出した結果を返します。
そこで
+[]
になります。
+""
というのも
[].join() === ""
.
ここでも
+
は次のように定義されます。
11.4.6 単項+演算子
単項演算子 + は、オペランドを Number 型に変換します。
プロダクションの UnaryExpression : + UnaryExpression は,次のように評価される。
UnaryExpressionの評価結果をexprとする。
ToNumber(GetValue(expr))を返します。
ToNumber
は、以下のように定義されています。
""
としています。
StringNumericLiteral :: のMVです。[empty]は0です。
そこで
+"" === 0
というように
+[] === 0
.
関連
-
JavaScriptの配列共通メソッド解説
-
[解決済み】JavaScriptエラー(Uncaught SyntaxError: Unexpected end of input)
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] event.preventDefault() vs. return false
-
[解決済み] JavaScriptで文字列をbooleanに変換するにはどうしたらいいですか?
-
[解決済み] 私のJavaScriptコードは "No 'Access-Control-Allow-Origin' header is present on requested resource "というエラーを受け取りますが、Postmanはそうならないのはなぜですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Vueのフィルタの説明
-
[解決済み】SyntaxError: JSONの位置1に予期しないトークンoがある。
-
[解決済み】Node Version Manager のインストール - nvm コマンドが見つかりません。
-
[解決済み】ローカルファイルを開くことができません - Chrome: ローカルリソースの読み込みが許可されていない
-
[解決済み】Node.js Error: Cannot find module express
-
[解決済み] TypeError: $.ajax(...) is not a function?
-
[解決済み】ERROR エラーです。スイッチのname属性が指定されていないフォームコントロールの値アクセッサがない
-
[解決済み】 env: node: macにそのようなファイルやディレクトリはありません
-
[解決済み】「.addEventListener is not a function」なぜこのエラーが発生するのか?
-
モジュールのビルドに失敗しました。Error: ENOENT: no such file or directory, scandir 'D:\.... \node_modules