(1,eval)(';this';)与JavaScript中的eval(';this';)对比?
我开始读书,有些人把我弄糊涂了(1,eval)(';this';)与JavaScript中的eval(';this';)对比?,javascript,eval,Javascript,Eval,我开始读书,有些人把我弄糊涂了 var global = (function () { return this || (1, eval)('this'); }()); 以下是我的问题: 问题1: (1,eval)==eval 它为什么以及如何工作 问题2:为什么不 var global = (function () { return this || eval('this'); }()); 或 Q1:多个用逗号分隔的连续javascript语句取最后一条语句的值。因此: (1,
var global = (function () {
return this || (1, eval)('this');
}());
以下是我的问题:
问题1:
(1,eval)==eval
它为什么以及如何工作
问题2:为什么不
var global = (function () {
return this || eval('this');
}());
或
Q1:多个用逗号分隔的连续javascript语句取最后一条语句的值。因此:
(1,eval)
获取最后一个值,该值是对eval()函数的函数引用。它显然是通过这种方式将eval()
调用转换为间接eval调用,该调用将在ES5的全局范围内进行评估。详细解释
问题2:一定有一些环境没有定义全局this
,但定义了eval('this')
。这是我能想到的唯一原因。到第1季度:
我认为这是JS中逗号运算符的一个很好的例子。我喜欢本文中对逗号运算符的解释:
逗号运算符计算其两个操作数(从左到右)并返回第二个操作数的值
至第二季度:
(1,eval)('this')
被视为间接eval调用,它在ES5中全局执行代码。因此,结果将是全球环境的变化
参见,(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
不能生成全局对象
可以收集更多的信息
编辑
显然,我的第一个问题的答案是“几乎总是”。直接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上花一周的时间。 < P>片段,
var global = (function () {
return this || (1, eval)('this');
}());
即使在严格模式下,也将正确计算全局对象。在非严格模式下,此
的值是全局对象,但在严格模式下它是未定义的
。表达式(1,eval)('this')
将始终是全局对象。这样做的原因涉及间接句directeval
的规则。对eval
的直接调用具有调用者的作用域,字符串this
将在闭包中计算为this
的值。间接eval
s在全局范围内求值,就像它们在全局范围内的函数内执行一样。由于该函数本身不是严格模式函数,全局对象作为this
传入,然后表达式this'
计算为全局对象。表达式(1,eval)
只是一种奇特的方式,可以强制eval
为间接的,并返回全局对象
A1:(1,eval)('this')
与eval('this')
不同,因为间接韵文直接调用eval
有特殊规则
A2:原始版本在严格模式下工作,修改后的版本没有。这里可以找到一个很好的解释:也许有人试图避开一个不允许/eval\(/g
?@stove)的签入钩子。是的,我也在想类似的事情。如果不是签入钩子,那么在这个过程中的某个地方会有一些过滤器(可能是最小化)。它与ES5严格模式有关。在ES5严格模式下,任何eval
'd代码都是在其自身的上下文中执行的,而不是在全局上下文或封闭上下文中执行的。解决此问题的一种方法是像所讨论的代码那样间接引用它。请看“”更新了我的答案,包含了来自CDSanchez和@Saxoier.Thx的信息。我更新了标题,因为这是一个特殊情况。另外,特定类型括号的括号:[]和{}完全不同:)哇,我不知道整个值vs左值的事情(实际上可能是这样,但不是用词).也不是ES5评估规则(我不应该合理地使用eval
ever)。谢谢!是的,eval
有很多令人讨厌的尖锐边缘,只能作为最后的手段,然后非常非常小心地使用。我只遇到过一次有效的用法-评估通过innerHtml
lvalue添加到DOM中的脚本标记与确定直接eval没有多大关系,因为它通常引用表达式that可以出现在赋值的左侧,因此名称为左值而不是右值。只有在规范15.1.2.1.1中列出的条件下,对eval的调用才是直接的,其中规定标识符必须是eval
,并且是调用表达式的MemberExpression部分,并引用标准eval
函数。@Malvolio你似乎在暗示左值与直接或间接评估有关,而它们与之无关
var global = (function () {
return this || (1, eval)('this');
}());