简体   繁体   English

(1, eval)('this') vs eval('this') 在 JavaScript 中?

[英](1, eval)('this') vs eval('this') in JavaScript?

I start to read JavaScript Patterns , some codes confused me.我开始阅读JavaScript Patterns ,一些代码让我感到困惑。

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

Here are my questions:以下是我的问题:

Q1:问题 1:

(1, eval) === eval ? (1, eval) === eval ?

Why and how does it work?为什么以及如何运作?

Q2: Why not just Q2:为什么不只是

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

or或者

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

The difference between (1,eval) and plain old eval is that the former is a value and the latter is an lvalue. (1,eval)和普通的旧eval之间的区别在于前者是一个,后者是一个左值。 It would be more obvious if it were some other identifier:如果是其他标识符会更明显:

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

That is (1,eval) is an expression that yields eval (just as say, (true && eval) or (0 ? 0 : eval) would), but it's not a reference to eval .也就是说(1,eval)是一个产生eval的表达式(就像说(true && eval)(0 ? 0 : eval)会),但它不是对eval的引用。

Why do you care?你为什么在乎?

Well, the Ecma spec considers a reference to eval to be a "direct eval call", but an expression that merely yields eval to be an indirect one -- and indirect eval calls are guaranteed to execute in global scope.好吧,Ecma 规范认为对eval引用是“直接 eval 调用”,但仅将eval成为间接表达式的表达式 - 并且保证间接 eval 调用在全局范围内执行。

Things I still don't know:我还不知道的事情:

  1. Under what circumstance does a direct eval call not execute in global scope?在什么情况下直接 eval 调用不在全局范围内执行?
  2. Under what circumstance can the this of a function at global scope not yield the global object?在什么情况下全局作用域的函数的this不能产生全局对象?

Some more information can be gleaned here .可以在此处收集更多信息。

EDIT编辑

Apparently, the answer to my first question is, "almost always".显然,我的第一个问题的答案是“几乎总是”。 A direct eval executes from the current scope.直接eval当前作用域执行。 Consider the following code:考虑以下代码:

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

Not surprisingly (heh-heh), this prints out:毫不奇怪(呵呵),这打印出来:

direct call: inner
indirect call: outer

EDIT编辑

After more experimentation, I'm going to provisionally say that this cannot be set to null or undefined .经过更多实验,我将暂时说this不能设置为nullundefined It can be set to other falsy values (0, '', NaN, false), but only very deliberately.它可以设置为其他虚假值(0、''、NaN、false),但只是非常有意。

I'm going to say your source is suffering from a mild and reversible cranio-rectal inversion and might want to consider spending a week programming in Haskell.我要说的是您的消息来源患有轻度且可逆的颅直肠倒置,可能需要考虑在 Haskell 上花一周时间进行编程。

The fragment片段

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

will correctly evaluate to the global object even in strict mode.即使在严格模式下也会正确评估全局对象。 In non-strict mode the value of this is the global object but in strict mode it is undefined .在非严格模式下this的值是全局对象,但在严格模式下它是undefined The expression (1, eval)('this') will always be the global object.表达式(1, eval)('this')将始终是全局对象。

The reason for this involves the rules around indirect versus direct eval .这样做的原因涉及有关间接与直接eval的规则。 Direct calls to eval has the scope of the caller and the string this would evaluate to the value of this in the closure.eval直接调用具有调用者的范围,并且this将评估为闭包中this的值的字符串。 Indirect eval s evaluate in global scope as if they were executed inside a function in the global scope.间接eval在全局范围内进行评估,就好像它们在全局范围内的函数内执行一样。

Since that function is not itself a strict-mode function the global object is passed in as this and then the expression 'this' evaluates to the global object.由于该函数本身不是严格模式函数,因此全局对象作为this传入,然后表达式'this'计算为全局对象。 The expression (1, eval) is just a fancy way to force the eval to be indirect and return the global object.表达式(1, eval)只是强制eval为间接并返回全局对象的一种奇特方式。

A1: (1, eval)('this') is not the same as eval('this') because of the special rules around indirect versus direct calls to eval . A1: (1, eval)('this')eval('this')因为关于间接调用与直接调用eval的特殊规则。

A2: The original works in strict mode, the modified versions do not. A2:原版在严格模式下工作,修改后的版本没有。

To Q1:至 Q1:

I think this is a good example of comma operator in JS.我认为这是 JS 中逗号运算符的一个很好的例子。 I like the explanation for comma operator in this article: http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/我喜欢这篇文章中对逗号运算符的解释: http : //javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/

The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.逗号运算符计算它的两个操作数(从左到右)并返回第二个操作数的值。

To Q2:至 Q2:

(1, eval)('this') is considered as indirect eval call, which in ES5 does execute code globally. (1, eval)('this')被认为是间接的 eval 调用,在 ES5 中它会全局执行代码。 So the result will be the global the context.所以结果将是全局上下文。

See http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scopehttp://perfectkills.com/global-eval-what-are-the-options/#evaling_in_global_scope

Q1: Multiple consecutive javascript statements separated by a comma take the value of the last statement. Q1:用逗号分隔的多个连续 javascript 语句取最后一条语句的值。 So:所以:

(1, eval) takes the value of the last one which is a function reference to the eval() function. (1, eval)取最后一个的值,它是对eval()函数的函数引用。 It apparently does it this way to make the eval() call into an indirect eval call that will be evaluated in the global scope in ES5.显然这样做是为了将eval()调用变成一个间接的 eval 调用,该调用将在 ES5 的全局范围内进行评估。 Details explained here .详细解释here

Q2: There must be some environment that doesn't define a global this , but does define eval('this') . Q2:一定有一些环境没有定义全局this ,但定义了eval('this') That's the only reason I can think of for that.这是我能想到的唯一原因。

I start to read JavaScript Patterns , some codes confused me.我开始阅读JavaScript模式,一些代码使我感到困惑。

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

Here are my questions:这是我的问题:

Q1: Q1:

(1, eval) === eval ? (1, eval) === eval

Why and how does it work?为什么以及如何运作?

Q2: Why not just Q2:为什么不只是

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

or或者

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM