为什么在使用Function构造函数进行动态代码求值时没有形成闭包

Why are closures not formed while doing dynamic code evaluation using the Function constructor?

本文关键字:闭包 代码 动态 Function 构造函数 为什么      更新时间:2023-09-26

那么,在动态代码评估的两种方法(Function constructoreval())中,前者不创建闭包,而后者创建闭包?为什么在使用Function构造函数评估某些代码时不形成闭包?ECMA规范是否规定了这种行为?

ECMA规范是否规定了这种行为?

是的。第15.3.2.1节描述了评估new Function时执行的算法。注意最后一步:

11.返回按照13.2中的指定创建的新Function对象,将p作为FormalParameterList,将body作为FunctionBody。在全局环境中作为Scope参数传入,并将strict作为strict标志传入。

函数将在其中运行的作用域是全局作用域,而不是进行调用的当前作用域,因此它不能形成闭包。

另一方面,通过eval执行的代码在当前范围内运行(§10.4.2):

b。将LexicalEnvironment设置为与调用执行上下文的LexicalEnvironment相同的值
c.将VariableEnvironment设置为与调用执行上下文的VariableEnvironment相同的值。

这里有一种查看函数eval影响闭包的方法。

var z = 0;
(function () {                                 // Local    | Global
    var x = 0, y = 0;                          // x  y  z  | x      y      z
    console.log(x, y, z);                      // 0  0  0  |
    console.log(window.x, window.y, window.z); //          | undef  undef  0
    new Function('var x = 1; y = 1; z = 1')(); // Function set 1
    console.log(x, y, z);                      // 0  0  1  |
    console.log(window.x, window.y, window.z); //          | undef  1      1
    eval('var x = 2; y = 2; z = 2');           // Eval set 2
    console.log(x, y, z);                      // 2  2  2  |
    console.log(window.x, window.y, window.z); //          | undef  1      2
}());

您可以看到eval在当前作用域中工作,而函数是作为全局作用域中的函数调用的。

但实际上,请尽量避免使用任何一种。