为什么复制eval会改变其行为?

问题描述 投票:2回答:1

根据 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的引用会使其行为发生如此巨大的变化?

javascript ecmascript-5 rollupjs
1个回答
3
投票

因为 ECMAScript 5语言规范 说,直接提到 eval 将在本地作用域中执行,而间接引用将使用全局作用域。

更多的英文描述可以在 MDN:

如果你通过eval以外的引用间接使用eval函数,从ECMAScript 5开始,它在全局范围内而不是局部范围内工作。这意味着,例如,函数声明创建了全局函数,被评估的代码不能访问被调用的作用域内的局部变量。

© www.soinside.com 2019 - 2024. All rights reserved.