web-dev-qa-db-ja.com

(1、eval)( 'this')vs eval( 'this')JavaScript?

私は JavaScriptパターン 、いくつかの コード を読み始めました。

var global = (function () {
    return this || (1, eval)('this');
}());

私の質問は次のとおりです。

Q1:

(1, eval) === eval

なぜ、どのように機能しますか?

Q2:どうして

var global = (function () {
    return this || eval('this');
}());

または

 var global = (function () {
    return this;
}());
79
shawjia

(1,eval)と従来のevalの違いは、前者がvalueであり、後者が左辺値であることです。それが他の識別子である場合、それはより明白です:

var x;
x = 1;
(1, x) = 1; //  syntax error, of course!

つまり(1,eval)eval(ちょうど(true && eval)または(0 ? 0 : eval)が返すように)を生成する式ですが、evalへの参照ではありません。

なんで気にするの?

まあ、ECMA仕様はevalへのreferenceを「直接eval呼び出し」と見なしますが、単にevalを生成する式は間接的と見なしますone-および間接的なeval呼び出しは、グローバルスコープでの実行が保証されています。

私がまだ知らないこと:

  1. どのような状況下で、直接のeval呼び出しnotはグローバルスコープで実行されますか?
  2. グローバルスコープnotの関数のthisはどのような状況でグローバルオブジェクトを生成できますか?

より多くの情報を収集できます here

[〜#〜] edit [〜#〜]

どうやら、私の最初の質問に対する答えは、「ほぼ常に」です。直接evalは、currentスコープから実行されます。次のコードを検討してください。

var x = 'outer';
(function() {
  var x = 'inner';
  eval('console.log("direct call: " + x)'); 
  (1,eval)('console.log("indirect call: " + x)'); 
})();

驚くことではありません(heh-heh)、これは次のように出力します:

direct call: inner
indirect call: outer

[〜#〜] edit [〜#〜]

さらに実験した後、thisnullまたはundefinedに設定できないと暫定的に言います。他の偽の値(0、 ''、NaN、false)に設定できますが、意図的にveryのみです。

あなたの情報源は軽度で可逆的な頭蓋直腸の反転に苦しんでおり、Haskellで1週間のプログラミングを費やすことを検討したいと思うでしょう。

94
Malvolio

フラグメント、

_var global = (function () {  
    return this || (1, eval)('this');  
}());  
_

strictモードでも、グローバルオブジェクトに対して正しく評価されます。非厳密モードでは、thisの値はグローバルオブジェクトですが、厳密モードではundefinedです。式_(1, eval)('this')_は常にグローバルオブジェクトになります。この理由には、間接_direct $ evalに関連するルールが含まれます。 evalの直接呼び出しには呼び出し元のスコープがあり、文字列thisはクロージャ内のthisの値に評価されます。間接evalsは、グローバルスコープの関数内で実行されたかのように、グローバルスコープで評価します。その関数自体はストリクトモード関数ではないため、グローバルオブジェクトはthisとして渡され、式_'this'_はグローバルオブジェクトに評価されます。式_(1, eval)_は、evalを強制的に間接的にして、グローバルオブジェクトを返すための単なる派手な方法です。

A1:_(1, eval)('this')_は、evalへの間接呼び出しと直接呼び出しに関する特別な規則があるため、eval('this')と同じではありません。

A2:オリジナルはストリクトモードで動作しますが、変更されたバージョンは動作しません。

30
chuckj

Q1へ:

これはJSのカンマ演算子の良い例だと思います。この記事のコンマ演算子の説明が好きです: http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/

コンマ演算子は、両方のオペランド(左から右)を評価し、2番目のオペランドの値を返します。

Q2へ:

(1, eval)('this')は、間接的なeval呼び出しと見なされ、ES5ではグローバルにコードを実行します。したがって、結果はグローバルなコンテキストになります。

http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope を参照してください

11
Grace Shao

Q1:コンマで区切られた複数の連続したjavascriptステートメントは、最後のステートメントの値を取ります。そう:

_(1, eval)_は、eval()関数への関数参照である最後の値を取ります。 eval()呼び出しを、ES5のグローバルスコープで評価される間接的なeval呼び出しにすることは、明らかにこの方法です。詳細説明 ここ

Q2:グローバルthisを定義せず、eval('this')を定義する環境が必要です。それが私が考えることができる唯一の理由です。

7
jfriend00