(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')
    将始终是全局对象。这样做的原因涉及间接句direct
    eval
    的规则。对
    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');  
    }());