CodeMash 2012 の「Wat」トークで言及されたこれらの奇妙な JavaScript の動作の説明は何ですか? 質問する

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>

JavaScript で配列で使用される演算子について非常に興味があります+。これはビデオの結果と一致します。

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 になるという単純な動作であると思われます。

ベストアンサー1

ここに、あなたが見ている(そして見ているは​​ずの)結果の説明のリストがあります。私が使用している参考文献は、ECMA-262 規格

  1. [] + []

    加算演算子を使用する場合、左オペランドと右オペランドの両方が最初にプリミティブに変換されます(§11.6.1)。§9.1、オブジェクト(この場合は配列)をプリミティブに変換するとデフォルト値が返されます。これは、有効なtoString()メソッドを持つオブジェクトの場合、 object.toString()§8.12.8)。配列の場合、これはarray.join()§15.4.4.2) 空の配列を結合すると空の文字列が生成されるため、加算演算子のステップ 7 では 2 つの空の文字列の連結、つまり空の文字列が返されます。

  2. [] + {}

    と同様に[] + []、両方のオペランドは最初にプリミティブに変換されます。「Objectオブジェクト」(§15.2)の場合、これは再び を呼び出した結果でありobject.toString()、nullでなく未定義でないオブジェクトの場合は"[object Object]"§15.2.4.2)。

  3. {} + []

    ここ{}ではオブジェクトとして解析されず、代わりに空のブロックとして解析されます(§12.1(少なくともその文を式にしない限りは、ですが、これについては後で詳しく説明します)。空のブロックの戻り値は空なので、その文の結果は と同じです+[]。単項+演算子(§11.4.6) は を返しますToNumber(ToPrimitive(operand))。既にご存知のとおり、ToPrimitive([])は空の文字列であり、§9.3.1ToNumber("")0です。

  4. {} + {}

    前のケースと同様に、最初の は{}空の戻り値を持つブロックとして解析されます。+{}は と同じでありToNumber(ToPrimitive({}))ToPrimitive({})は です"[object Object]"( を参照[] + {})。したがって、 の結果を得るには、文字列 に+{}適用する必要があります。ToNumber"[object Object]"§9.3.1NaN結果として次のようになります。

    文法がStringをStringNumericLiteralの展開として解釈できない場合、宛先番号NaNです。

  5. Array(16).join("wat" - 1)

    に従って§15.4.1.1そして§15.4.2.2Array(16)長さ16の新しい配列を作成します。結合する引数の値を取得するには、§11.6.2ステップ5と6は、両方のオペランドを を使用して数値に変換する必要があることを示していますToNumberToNumber(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 に強制されるため空のブロックとして解析できなくなり{}、代わりに空のオブジェクトリテラルとして解析されます。

おすすめ記事