私は 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;
}());
(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呼び出しは、グローバルスコープでの実行が保証されています。
私がまだ知らないこと:
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 [〜#〜]
さらに実験した後、this
をnull
またはundefined
に設定できないと暫定的に言います。他の偽の値(0、 ''、NaN、false)に設定できますが、意図的にveryのみです。
あなたの情報源は軽度で可逆的な頭蓋直腸の反転に苦しんでおり、Haskellで1週間のプログラミングを費やすことを検討したいと思うでしょう。
フラグメント、
_var global = (function () {
return this || (1, eval)('this');
}());
_
strictモードでも、グローバルオブジェクトに対して正しく評価されます。非厳密モードでは、this
の値はグローバルオブジェクトですが、厳密モードではundefined
です。式_(1, eval)('this')
_は常にグローバルオブジェクトになります。この理由には、間接_direct $ eval
に関連するルールが含まれます。 eval
の直接呼び出しには呼び出し元のスコープがあり、文字列this
はクロージャ内のthis
の値に評価されます。間接eval
sは、グローバルスコープの関数内で実行されたかのように、グローバルスコープで評価します。その関数自体はストリクトモード関数ではないため、グローバルオブジェクトはthis
として渡され、式_'this'
_はグローバルオブジェクトに評価されます。式_(1, eval)
_は、eval
を強制的に間接的にして、グローバルオブジェクトを返すための単なる派手な方法です。
A1:_(1, eval)('this')
_は、eval
への間接呼び出しと直接呼び出しに関する特別な規則があるため、eval('this')
と同じではありません。
A2:オリジナルはストリクトモードで動作しますが、変更されたバージョンは動作しません。
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 を参照してください
Q1:コンマで区切られた複数の連続したjavascriptステートメントは、最後のステートメントの値を取ります。そう:
_(1, eval)
_は、eval()
関数への関数参照である最後の値を取ります。 eval()
呼び出しを、ES5のグローバルスコープで評価される間接的なeval呼び出しにすることは、明らかにこの方法です。詳細説明 ここ 。
Q2:グローバルthis
を定義せず、eval('this')
を定義する環境が必要です。それが私が考えることができる唯一の理由です。