(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; }());
谁能告诉我? 谢谢。
(1,eval)
和普通的旧eval
的区别在于前者是一个值 ,后者是左值。 如果它是一些其他的标识符会更明显:
var x; x = 1; (1, x) = 1; // syntax error, of course!
那就是(1,eval)
是一个产生eval
的expression式(就像说, (true && eval)
或(0 ? 0 : eval)
会),但它不是对eval
的引用。
你为什么在乎?
那么,Ecma规范认为对eval
的引用是一个“直接eval调用”,但是仅仅产生一个eval
是一个间接的expression式,而间接的eval调用则保证在全局范围内执行。
事情我还是不知道:
- 在全球范围内,在什么情况下不进行直接评估?
- 在什么情况下全球范围内的一个function
this
不会产生全球性的客体?
这里可以find更多的信息。
编辑
显然,我的第一个问题的答案是“几乎总是”。 直接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
。 它可以设置为其他的falsy值(0,'',NaN,false),但只是非常慎重。
我要说,你的来源正在遭受轻度和可逆的颅 – 直肠倒置,可能要考虑在Haskell花费一周的时间。
片段,
var global = (function () { return this || (1, eval)('this'); }());
即使在严格模式下也会正确评估全局对象。 在非严格模式下,这个值是全局对象,但在严格模式下是undefined
。 expression式(1, eval)('this')
将始终是全局对象。 其原因涉及间接诗句直接eval
的规则。 直接调用eval
的调用者的范围和string, this
将计算在封闭的this
值。 间接评估在全局范围内评估,就好像它们是在全局范围内的一个函数内部执行一样。 由于该函数本身不是严格模式函数,所以全局对象以this
方式传入,然后expression式'this'
求值为全局对象。 expression式(1, eval)
只是强制eval
间接返回全局对象的一种奇特的方式。
A1: (1, eval)('this')
是不一样的,因为间接的直接调用eval
的特殊规则。
A2:原作在严格模式下,修改版本不行。
对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
Q1:以逗号分隔的多个连续的JavaScript语句取最后一条语句的值。 所以:
(1, eval)
取最后一个参数为eval()
函数的函数的值。 显然这样做是为了使eval()
调用成为一个间接的eval调用,将在ES5的全局范围中进行评估。 细节在这里解释。
问题2:必须有一些没有定义全局的环境,但是确定了eval('this')
。 这是我能想到的唯一原因。