(1, eval)('this') vs eval('this') 在 JavaScript 中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9107240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
(1, eval)('this') vs eval('this') in JavaScript?
提问by shawjia
I start to read JavaScript Patterns, some codesconfused 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;
}());
回答by Malvolio
The difference between (1,eval)
and plain old eval
is that the former is a valueand the latter is an lvalue. It would be more obvious if it were some other identifier:
(1,eval)
和plain old之间的区别在于eval
前者是一个值,后者是一个左值。如果是其他标识符会更明显:
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
(就像 say(true && eval)
或(0 ? 0 : eval)
will 一样),但它不是对eval
.
Why do you care?
你为什么在乎?
Well, the Ecma spec considers a referenceto 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:
我还不知道的事情:
- Under what circumstance does a direct eval call notexecute in global scope?
- Under what circumstance can the
this
of a function at global scope notyield the global object?
- 在什么情况下直接 eval 调用不在全局范围内执行?
- 在什么情况下
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 currentscope. Consider the following code:
显然,我的第一个问题的答案是“几乎总是”。eval
从当前作用域直接执行。考虑以下代码:
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
. It can be set to other falsy values (0, '', NaN, false), but only verydeliberately.
经过更多的实验,我将暂时说this
不能设置为null
或undefined
。它可以设置为其他虚假值(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 上花一周时间进行编程。
回答by chuckj
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
. The expression (1, eval)('this')
will always be the global object. The reason for this involves the rules around indirect verses direct 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. Indirect eval
s evaluate in global scope as if they were executed inside a function in the global scope. 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. The expression (1, eval)
is just a fancy way to force the eval
to be indirect and return the global object.
即使在严格模式下也会正确评估全局对象。在非严格模式下, 的值this
是全局对象,但在严格模式下是undefined
。表达式(1, eval)('this')
将始终是全局对象。这样做的原因涉及围绕间接诗句 direct 的规则eval
。直接调用eval
具有调用者的范围,并且字符串this
将评估为this
闭包中的值。Indirect eval
s 在全局范围内进行评估,就好像它们在全局范围内的函数内执行一样。由于该函数本身不是严格模式函数,因此全局对象被传入 asthis
然后表达式'this'
计算为全局对象。该表达式(1, eval)
只是一种强制eval
是间接的并返回全局对象。
A1: (1, eval)('this')
is not the same as eval('this')
because of the special rules around indirect verse direct calls to eval
.
A1:(1, eval)('this')
不一样,eval('this')
因为围绕间接诗句直接调用的特殊规则eval
。
A2: The original works in strict mode, the modified versions do not.
A2:原版在严格模式下工作,修改后的版本没有。
回答by Grace Shao
To Q1:
至 Q1:
I think this is a good example of comma operator in JS. I like the explanation for comma operator in this article: http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
我认为这是 JS 中逗号运算符的一个很好的例子。我喜欢这篇文章中对逗号运算符的解释: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. So the result will be the global the context.
(1, eval)('this')
被认为是间接 eval 调用,在 ES5 中它会全局执行代码。所以结果将是全局上下文。
See http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope
见http://perfectkills.com/global-eval-what-are-the-options/#evaling_in_global_scope
回答by jfriend00
Q1: Multiple consecutive javascript statements separated by a comma take the value of the last statement. So:
Q1:用逗号分隔的多个连续 javascript 语句取最后一条语句的值。所以:
(1, eval)
takes the value of the last one which is a function reference to the eval()
function. 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. Details explained here.
(1, eval)
取最后一个的值,该值是对函数的函数引用eval()
。显然这样做是为了将eval()
调用变成间接 eval 调用,该调用将在 ES5 的全局范围内进行评估。详情在这里解释。
Q2: There must be some environment that doesn't define a global this
, but does define eval('this')
. That's the only reason I can think of for that.
Q2:一定有一些环境没有定义 global this
,但确实定义了eval('this')
. 这是我能想到的唯一原因。