我开始阅读JavaScript Patterns,有些codes让我困惑。
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;
}());
答案 0 :(得分:91)
(1,eval)
和普通旧eval
之间的区别在于前者是值,后者是左值。如果它是其他标识符会更明显:
var x;
x = 1;
(1, x) = 1; // syntax error, of course!
即(1,eval)
是一个表达式eval
(就像(true && eval)
或(0 ? 0 : eval)
那样),但它不是对eval
的引用
为什么要关心?
好吧,Ecma规范认为引用到eval
是一个“直接eval调用”,但这个表达只会使eval
成为间接调用 - - 并保证间接eval调用在全局范围内执行。
我还不知道的事情:
this
不会产生全局对象?可以收集更多信息here。
编辑
显然,我的第一个问题的答案是“几乎总是”。直接eval
从当前范围执行。请考虑以下代码:
var x = 'outer';
(function() {
var x = 'inner';
eval('console.log("direct call: " + x)');
(1,eval)('console.log("indirect call: " + x)');
})();
毫不奇怪(嘿嘿),这打印出来:
direct call: inner
indirect call: outer
修改强>
经过更多实验,我暂时会说this
无法设置为null
或undefined
。它可以设置为其他有价值的值(0,'',NaN,false),但只能非常。
我要说你的来源患有轻微且可逆的颅内直肠反转,并且可能想考虑在Haskell中花一周时间编程。
答案 1 :(得分:30)
片段,
var global = (function () {
return this || (1, eval)('this');
}());
即使在严格模式下,也会正确评估全局对象。在非严格模式下,this
的值是全局对象,但在严格模式下,它是undefined
。表达式(1, eval)('this')
将始终是全局对象。其原因涉及间接经文直接eval
的规则。对eval
的直接调用具有调用者的作用域,字符串this
将在闭包中计算为this
的值。间接eval
在全局范围内进行评估,就好像它们是在全局范围内的函数内执行一样。由于该函数本身不是严格模式函数,因此全局对象作为this
传入,然后表达式'this'
求值为全局对象。表达式(1, eval)
只是强制eval
为间接并返回全局对象的一种奇特方式。
A1:(1, eval)('this')
与eval('this')
不同,因为有关间接诗歌直接调用eval
的特殊规则。
A2:原版在严格模式下工作,修改后的版本不工作。
答案 2 :(得分:11)
到Q1:
我认为这是JS中逗号运算符的一个很好的例子。我喜欢本文中逗号运算符的解释:http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
逗号运算符计算它的两个操作数(从左到右)并返回第二个操作数的值。
到Q2:
(1, eval)('this')
被视为间接eval调用,在ES5中执行全局代码。因此,结果将是全球化的背景。
请参阅http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope
答案 3 :(得分:7)
Q1:用逗号分隔的多个连续的javascript语句取最后一个语句的值。所以:
(1, eval)
获取最后一个的值,该值是eval()
函数的函数引用。它显然是这样做的,使eval()
调用成为间接eval调用,将在ES5的全局范围内进行评估。细节解释here。
Q2:必须有一些环境不能定义全局this
,但确定eval('this')
。这是我能想到的唯一原因。