为什么EcmaScript 5严格模式会限制标识符“eval”

时间:2009-12-19 19:35:10

标签: javascript security eval ecmascript-5

根据spec(附件C),严格模式代码几乎不能做任何可能分配名称为eval的任何标识符的内容。我可以理解,可能想要限制实际eval函数的使用,但是我没有看到限制使用该名称的目的是什么?

2 个答案:

答案 0 :(得分:10)

bobince基本上是正确的。 (我在SpiderMonkey上工作,Mozilla的JS引擎,已经在其中实现了ES5的各个部分,并且在时间允许的情况下遵循ECMAScript讨论。)您(实现者和读者都)确实希望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严格意味着evalarguments应该被视为原始语法,而不是标识符。这两个特征应该在句法层面实现是合理的,因为它们具有神奇的时髦魔法行为,不能通过正常的功能再现。

(特别是eval可能会在调用它的函数中写入局部变量,写入arguments会奇怪地改变与参数对应的局部变量的值。虽然这种行为似乎正在发生谢天谢地,在严格的模式下。)

出于兼容性原因,ES5实际上无法使evalarguments语法化。所以他们尽可能地做到最近,也就是说标识符arguments总是引用arguments魔法,标识符eval总是专指eval魔法。

如果JS引擎可以确定函数是否包含魔法,它还可以提高优化的可能性。