JavaScript 中的每个函数都是闭包是真的吗?

IT技术 javascript closures ecmascript-5
2021-01-18 00:12:50

我知道 JavaScript 中的每个函数都是一等对象,它有一个内部属性 [[scope]] ,它承载函数自由变量的绑定记录。但是,有两种特殊情况。

  1. Function构造函数创建的函数也是闭包吗?Function 构造函数创建的函数对象是特殊的,因为它的 [[scope]] 可能不是指其外部函数的词法环境,而只是全局上下文。例如,

    var a = 1; 
    var fn = (function outer() {
        var a = 2; 
        var inner = new Function('alert(a); ');
        return inner;
    })();
    fn(); // will alert 1, not 2.
    

    这是不直观的。这也叫闭包?

  2. 如果一个内部函数没有任何自由变量,我们可以说创建内部函数时就形成了一个闭包吗?例如,

    // This is a useless case only for academic study
    var fn = (function outer() {
        var localVar1 = 1,
            localVar2 = 2;
        return function() {};
    })();
    

    在这种情况下, fn 指的是作为内部函数创建的空函数对象。它没有自由变量。在这种情况下,我们可以说形成了一个闭包吗?

2个回答

Function构造函数创建的函数也是闭包吗?

是的,它关闭了全局范围。这可能是不直观的,因为所有其他 JavaScript 闭包都在其词法范围内关闭,但它仍然符合我们对闭包定义在您的示例中,a是一个自由变量,ainner/fn函数在某处被调用,它会解析为另一个作用域中的

如果一个内部函数没有任何自由变量,我们还能称它为闭包吗?

取决于你问谁。有人说是,其他人称它们为“无趣的闭包”,我个人说不,因为它们不引用外部作用域。

好吧,如果你遵循ES5规范的[[适用范围]]的inner商店的词法环境outer,其outera变量-所以一切都还可以访问和记忆。如果您遵循实际的 ES 实现,并inner使用您的调试器进行检查,您将看不到任何范围引用——它不需要它们,因为没有自由变量。
2021-03-14 00:12:50
谢谢@Bergi,精彩的解释。在第二种情况下,outer() 函数将在我们执行代码后被垃圾收集,因为它不再被引用。但是 fn 的 [[scope]] 内部属性是什么?或者简单地说,函数对象 fn 所指的是否记得它是在外层()范围内创建的?
2021-04-12 00:12:50

注意:使用 Function 构造函数创建的函数不会为其创建上下文创建闭包;它们总是在全局范围内创建。运行它们时,它们只能访问自己的局部变量和全局变量,而不能访问调用 Function 构造函数的范围内的变量。这与将 eval 与函数表达式的代码一起使用不同。

来自https://developer.mozilla.org