根据spec(附件C),严格模式代码几乎不能做任何可能分配名称为eval
的任何标识符的内容。我可以理解,可能想要限制实际eval
函数的使用,但是我没有看到限制使用该名称的目的是什么?
答案 0 :(得分:10)
eval
成为规范{{1您希望eval
成为规范arguments
。使用严格模式你可以获得这个。
但我要指出,ES5在这方面的限制并不是所希望的。首先,要稍微纠正bobince,即使使用严格模式,您也无法确定arguments
是原始的eval
函数:
eval
这是众所周知的(在JS爱好者中)全局对象错误:脚本使用全局对象,跨脚本共享,可命名和可修改,以解析名称。如果您无法引用全局变量绑定的对象,则不会出现此问题。 ES6可能会通过另一个选择加入系统(可能是带外类型的MIME类型,但目前还不清楚)来解决这个问题。它总是限定整个脚本。
但即使没有可命名的,可变的全局对象,你仍然会遇到问题,因为严格的模式可以限定为函数:
"use strict";
this.eval = function() { return "ohai"; };
eval("7 + 10"); // "ohai"
即使存在严格模式,这些问题也存在,并且它们最早会在ES6之前消失,因为它可能会删除全局对象并无条件地强制执行严格的模式限制。
所以function outer()
{
var eval = function() { return "kthxbai"; };
function inner()
{
"use strict";
return eval("2 + 5");
}
return inner();
}
outer(); // "kthxbai"
在严格模式下仍然有点奇怪,因为它可以引用not-eval。但处理这并不是什么大问题 - 在运行时,实现可以检查真实的eval
,如果失败,只要执行语法恰好使用eval
以外的名称。这要求特别处理像eval
这样的表达式。但无论如何,任何好的实现都会这样做,因为eval(...)
的非静态可观察行为(改变局部变量和参数,引入新变量[现在以严格模式取消 - 在严格模式下的变量声明eval代码]是eval代码的本地代码,等等),所以这不是真正的负担。
值得注意的是,eval
作为假的特殊形式,这一点都不适用。要么通过函数范围有严格模式,在这种情况下你会看到 函数的arguments
而不是arguments
在外部范围内分配,或者你有它通过全局范围,arguments
没有特殊行为。 (为什么在全局严格模式代码中禁止arguments
的变异?可能简单,加上迫使开发人员将它们视为一种特殊形式,但我不确定。)
答案 1 :(得分:7)
我只能推测,但在我看来,ES5严格意味着eval
和arguments
应该被视为原始语法,而不是标识符。这两个特征应该在句法层面实现是合理的,因为它们具有神奇的时髦魔法行为,不能通过正常的功能再现。
(特别是eval
可能会在调用它的函数中写入局部变量,写入arguments
会奇怪地改变与参数对应的局部变量的值。虽然这种行为似乎正在发生谢天谢地,在严格的模式下。)
出于兼容性原因,ES5实际上无法使eval
和arguments
语法化。所以他们尽可能地做到最近,也就是说标识符arguments
总是引用arguments
魔法,标识符eval
总是专指eval
魔法。
如果JS引擎可以确定函数是否包含魔法,它还可以提高优化的可能性。