【问题标题】:Why doesn't strict mode restrict the identifiers "eval", and "arguments" from appearing as label names?为什么严格模式不限制标识符“eval”和“arguments”作为标签名称出现?
【发布时间】:2012-09-24 00:49:36
【问题描述】:

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

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

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

不过,这条规则有三个例外。 eval/arguments 不能出现 (1) 作为赋值的左侧表达式(例如 eval = true;),(2)作为 ++/-- 的操作数(例如 eval++),(3 ) 作为delete 的操作数(例如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 函数无关。

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

【问题讨论】:

  • 您应该通过es5-discuss 讨论列表询问参与编写 ES5 的人员。你可能只会在这里得到猜想——有一些可以开始的。 :-)
  • @alex 关于你的 Twitter 回复,如你所见,Stack Overflow 没有让你失望:)

标签: javascript theory


【解决方案1】:

我不知道为什么,但我可以大胆猜测。

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

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

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

【讨论】:

  • 是的,我认为最后一段很好地解释了做出此决定时 TC-39 中最有可能发生的情况。对我来说已经足够好了,我接受了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
相关资源
最近更新 更多