为什么复制 eval 会改变它的行为?

2024-04-24

根据rollupjs 文档 https://rollupjs.org/guide/en/#eval2--eval:

简单地“复制” 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 规范中。

Perhaps 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 语言规范 http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.2说直接引用eval将在本地范围内执行,而间接引用将使用全局范围。

可以在以下位置找到更适合英语的描述MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval:

如果您间接使用 eval 函数,通过 eval 以外的引用调用它,则从 ECMAScript 5 开始,它在全局范围而不是本地范围中工作。例如,这意味着函数声明创建全局函数,并且正在评估的代码无法访问调用它的范围内的局部变量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么复制 eval 会改变它的行为? 的相关文章

随机推荐