根据 rollupjs文档:
简单地 "复制 "eval为你提供了一个做同样事情的函数,但它在全局范围内而不是本地范围内运行。
var eval2 = eval;
(function () {
var foo = 42;
eval('console.log("with eval:",foo)'); // logs 'with eval: 42'
eval2('console.log("with eval2:",foo)'); // throws ReferenceError
})();
谁能解释一下这到底是怎么回事?我一直没能找到任何具体的关于 eval()
在ECMAScript规范中。
也许 eval
其实并不是一个函数,而是一个神奇的标记,它被一个在该作用域中执行代码的函数所取代,有点像这样。
var eval2 = CREATE_EVAL(CURRENT_SCOPE);
(function () {
var foo = 42;
CREATE_EVAL(CURRENT_SCOPE)('console.log("with eval:",foo)'); // logs 'with eval: 42'
eval2('console.log("with eval2:",foo)'); // throws ReferenceError
})();
然而,由于我们在这里处理的是模块(commonJS或ES6),这意味着 eval2
实际上是在模块范围内运行的。rollupjs文档中明确指出它是在全局范围内运行的--我想这只是一个疏忽,但当我测试时,它确实看起来是在全局范围内运行的。
var x = 1;
var eval2 = eval;
(function () {
eval2('console.log("with eval2:", x)'); // throws ReferenceError
})();
这让人很困惑 这到底是怎么做到的?为什么复制对eval的引用会使其行为发生如此巨大的变化?
因为 ECMAScript 5语言规范 说,直接提到 eval
将在本地作用域中执行,而间接引用将使用全局作用域。
更多的英文描述可以在 MDN:
如果你通过eval以外的引用间接使用eval函数,从ECMAScript 5开始,它在全局范围内而不是局部范围内工作。这意味着,例如,函数声明创建了全局函数,被评估的代码不能访问被调用的作用域内的局部变量。