[解決済み] CodeMash 2012の'Wat'トークで言及された、この奇妙なJavaScriptの動作の説明とは?
質問
その CodeMash 2012の「Wat」トーク RubyとJavaScriptの奇妙な癖をいくつか指摘しています。
その結果をJSFiddleにしました。 http://jsfiddle.net/fe479/9/ .
JavaScript特有の動作は(Rubyを知らないので)以下の通りです。
JSFiddleでは、私の結果がビデオの結果と一致しないものがありましたが、その理由はよくわかりません。しかし、私はそれぞれのケースでJavaScriptが裏でどのように処理されているのか知りたいと思っています。
Empty Array + Empty Array
[] + []
result:
<Empty String>
がかなり気になるところです。
+
演算子を使用することができます。
これはビデオの結果と一致します。
Empty Array + Object
[] + {}
result:
[Object]
これは動画の結果と一致します。どうなっているんだろう?なぜこれがオブジェクトなのか。は何をするのでしょうか?
+
演算子は何をするのですか?
Object + Empty Array
{} + []
result:
[Object]
これはビデオと一致しない。ビデオでは結果が0になるようですが、私は[Object]を得ました。
Object + Object
{} + {}
result:
[Object][Object]
これも動画と一致しないし、変数を出力するとどうして2つのオブジェクトになるのか?私のJSFiddleがおかしいのかもしれません。
Array(16).join("wat" - 1)
result:
NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
wat + 1 を実行すると
wat1wat1wat1wat1
...
これは、文字列から数値を引こうとするとNaNになってしまうという、素直な動作なのではないでしょうか。
解決方法は?
あなたが見ている(と思われる)結果について、解説をまとめました。使用しているリファレンスは ECMA-262規格 .
-
[] + []
加算演算子を使用する場合、左右のオペランドはともに最初にプリミティブに変換されます( §11.6.1 ). と同様に §9.1 オブジェクト(この場合は配列)をプリミティブに変換すると、そのデフォルト値が返されます。
toString()
メソッドを呼び出した結果です。object.toString()
( §8.12.8 ). 配列の場合、これは以下のように呼び出すのと同じです。array.join()
( §15.4.4.2 ). 空の配列を結合すると空の文字列になるので、加算演算子のステップ#7は2つの空の文字列の連結を返し、それは空の文字列となります。 -
[] + {}
と同様です。
[] + []
の場合、両オペランドはまずプリミティブに変換される。オブジェクトオブジェクト(15.2)の場合、これは再びobject.toString()
NULLでない、未定義でないオブジェクトの場合は、次のようになります。"[object Object]"
( §15.2.4.2 ). -
{} + []
は
{}
はオブジェクトとしてではなく、空のブロックとしてパースされます ( §12.1 少なくとも、そのステートメントを無理に式にしない限りは、ですが、それについては後で詳しく説明します)。空のブロックの戻り値は空なので、その文の結果は次のものと同じです。+[]
. 単項の+
演算子( §11.4.6 を返します。ToNumber(ToPrimitive(operand))
. すでにご存知のようにToPrimitive([])
は空の文字列であり §9.3.1 ,ToNumber("")
は0である。 -
{} + {}
先ほどのケースと同様に、最初の
{}
は空の戻り値を持つブロックとしてパースされます。もう一度+{}
と同じです。ToNumber(ToPrimitive({}))
であり、かつToPrimitive({})
は"[object Object]"
(参照[] + {}
). そのため、結果を得るために+{}
を適用する必要があります。ToNumber
という文字列の上に"[object Object]"
. の手順を踏むと §9.3.1 となります。NaN
ということになります。の展開として解釈できない場合、文法はその文字列を 文字列数値リテラル の結果は 数値へ は NaN .
-
Array(16).join("wat" - 1)
による §15.4.1.1 および §15.4.2.2 ,
Array(16)
は長さ16の新しい配列を作成します。結合する引数の値を取得する。 §11.6.2 ステップ #5 と #6 では、両方のオペランドを数値に変換するためにToNumber
.ToNumber(1)
は単純に1( §9.3 ) であるのに対しToNumber("wat")
はまたNaN
と同じように §9.3.1 . の手順 7 に従います。 §11.6.2 , §11.6.3 は次のように定めています。もし、どちらかのオペランドが NaN の場合、その結果は NaN .
ということは、引数で
Array(16).join
はNaN
. 15.4.4.5に従って(Array.prototype.join
を呼び出す必要があります。ToString
である引数に"NaN"
( §9.8.1 ):もし m は NaN という文字列を返します。
"NaN"
.のステップ10に続いて §15.4.4.5 の連結が15回繰り返されることになります。
"NaN"
と空の文字列が表示され、あなたが見ている結果と同じになります。 このとき"wat" + 1
の代わりに"wat" - 1
を引数として与えると、加算演算子は1
を文字列に変換するのではなく"wat"
を数値に変換しているので、実質的にArray(16).join("wat1")
.
について、異なる結果が表示される理由については、次のとおりです。
{} + []
の場合です。関数の引数として使用する場合、ステートメントを強制的に
ExpressionStatement
をパースすることができなくなります。
{}
を空のブロックとして解析し、その代わりに空のオブジェクト リテラルとして解析します。
関連
-
jQueryのコピーオブジェクトの説明
-
[解決済み】React-Redux: アクションはプレーンオブジェクトでなければならない。非同期アクションにはカスタムミドルウェアを使用する
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] とは何ですか! (not not)演算子とは何ですか?
-
[解決済み] JavaScriptの変数のスコープとは何ですか?
-
[解決済み] JavaScriptの「new」キーワードとは何ですか?
-
[解決済み] jQueryでJavaScriptオブジェクトから選択する際に、オプションを追加する最も良い方法は何ですか?
-
[解決済み] JavaScriptのnullとundefinedの違いは何ですか?
-
[解決済み】JavaScript版sleep()とは?)
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
vue3.0プロジェクトのアーキテクチャを構築するための便利なツール
-
[解決済み】最大呼び出しスタックサイズ超過エラー
-
[解決済み】Uncaught SyntaxError: JSONの位置0に予期しないトークンuがあります。
-
[解決済み】Node.js getaddrinfo ENOTFOUND
-
[解決済み】 `string.split is not a function` というエラーの原因は何ですか?
-
[解決済み】React Uncaught Error: 対象コンテナが DOM 要素でない [重複]。
-
[解決済み】リクエストに失敗していないのに、「TypeError: failed to fetch」が表示される。
-
Uncaught TypeError: null のプロパティ 'offsetHeight' を読み取れませんでした。
-
JSクリックイベント - Uncaught TypeError: プロパティ 'onclick' に null を設定できません。
-
OSSアップロードエラーを解決する: net::ERR_SSL_PROTOCOL_ERROR