0

因此,您可能知道,JavaScript 的严格模式对标识符eval和增加了限制arguments,有效地使它们成为保留字,但有两个例外:

  • 它们仍然可以用作表达式,即在需要表达式的地方(尽管有几个例外),
  • 它们仍然可以用作标签名称,并在break/continue语句中引用标签。

现在,我明白了第一个子弹。例如,如果标识符eval不允许作为表达式(并且真正的保留字不允许),我们将根本无法调用该eval函数(因为eval(str)是表达式)。也是如此arguments——我们需要能够将其用作表达式以便能够访问其元素(例如arguments[0])。

不过,这条规则有三个例外。eval/arguments可能不会出现 (1) 作为赋值中的左侧表达式 (eg eval = true;),(2) 作为++/的操作数--(eg eval++), (3) 作为delete(eg delete eval) 的操作数。这些是唯一的例外,在所有其他表达式上下文中,它们是有效的。

我不明白的是第二个子弹。为什么它们仍然可以用作标签名称?例如,此代码即使在严格模式下也有效:

eval: for ( var i = 0; i < 10; i++ ) {
    arguments: for ( var j = 0; j < 10; j++ ) {
        if ( i < j ) continue eval;
        console.log( i - j );    
    }        
}

注意如何continue eval;引用标签,与实际功能eval无关。eval

另外,请注意真正的保留字不能用作标签名称。据我了解,严格模式的目的是使 namesevalarguments保留字尽可能相似。那为什么要把它们作为有效的标签名称呢?

4

1 回答 1

1

我不知道为什么,但我可以冒险一个很好的猜测。

限制变量名的原因(eval以及为什么被禁止)是因为它们会影响变量名的绑定位置(即局部变量、封闭范围内的变量或全局对象上的属性,如果一个存在)。如果没有这些限制,一些名称在运行时之前是未绑定的,这意味着所有的危险。argumentswith

标签名称占用与变量名称、属性名称等不同的命名空间。break/的目标永远不会有歧义continue,因为标签是静态分配的,标签引用是静态解析的。(是的,eval代码可以包含标签。但是现有的跳转不能以这些标签eval为目标,代码中的跳转也不能以预先存在的标签为目标,因为标签解析发生在编译时,并且它的范围为程序,以使用 ECMAScript 终端的名称。包含eval调用的脚本是程序,调用执行的代码eval是程序,但出于标签定位的目的,两者是完全分开的。)

禁止变量名的原因eval根本arguments不适用于标签。因此,标签仍然可以命名为evalor arguments。以这种方式命名标签将是愚蠢的,真的。如果有人再次设计 ECMAScript/JavaScript,它们将是关键字,不能用作标签名称。但是禁止将它们作为标签名称并没有任何好处,并且至少有一个小的兼容性论点可以证明不禁止它们,因此它们没有被禁止。

于 2012-09-25T17:22:55.680 回答