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

JavaScript中的每个函数都是闭包,这是真的吗?,javascript,closures,ecmascript-5,Javascript,Closures,Ecmascript 5,我知道JavaScript中的每个函数都是一级对象,它有一个内部属性[[scope]],托管函数自由变量的绑定记录。然而,有两种特殊情况 函数构造函数创建的函数也是闭包吗?函数构造函数创建的函数对象是特殊的,因为它的[[scope]]可能不引用其外部函数的词法环境,而只引用全局上下文。比如说, var a = 1; var fn = (function outer() { var a = 2; var inner = new Function('alert(a); ');

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

  • 函数构造函数创建的函数也是闭包吗?函数构造函数创建的函数对象是特殊的,因为它的[[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.
    
    // This is a useless case only for academic study
    var fn = (function outer() {
        var localVar1 = 1,
            localVar2 = 2;
        return function() {};
    })();
    
    这是不直观的。这也叫闭包吗

  • 如果一个内部函数没有任何自由变量,我们能说在创建内部函数时形成了闭包吗?比如说,

    var a = 1; 
    var fn = (function outer() {
        var a = 2; 
        var inner = new Function('alert(a); ');
        return inner;
    })();
    fn(); // will alert 1, not 2.
    
    // This is a useless case only for academic study
    var fn = (function outer() {
        var localVar1 = 1,
            localVar2 = 2;
        return function() {};
    })();
    
    在这种情况下,fn指的是作为内部函数创建的空函数对象。它没有自由变量。在这种情况下,我们可以说一个闭包形成了吗

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

    是的,它在全球范围内关闭。这可能是不直观的,因为所有其他JavaScript闭包都在其词法范围内关闭,但它仍然符合我们的要求。在您的示例中,
    a
    是一个自由变量,当在某个地方调用
    内部
    /
    fn
    函数时,它解析为另一个作用域中的
    a

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

    这取决于你问谁。说“是”,称之为“无趣闭包”,我个人说“否”,是因为一个外部范围

    注意:使用函数构造函数创建的函数不会创建 关闭他们的创作环境;它们总是在中创建的 全球范围。运行它们时,它们将只能访问 它们自己的局部变量和全局变量,而不是范围内的变量 其中调用了函数构造函数。这与 将eval与函数表达式的代码一起使用


    中,您对“关闭”的定义是什么?这里提供了关于此行为的进一步评论:该行为似乎与
    eval
    行为(间接调用与直接调用)相关。另请参见此处:——“使用函数构造函数创建的函数不会创建其创建上下文的闭包;它们总是在全局范围内创建的。”问题2更像是一个哲学性的“如果一棵树倒在森林里”问题。@Mörrenoshine感谢Ben Nadel的帖子和MDN的链接。感谢@Bergi,精彩的解释。在第二种情况下,outer()函数将在执行代码后被垃圾收集,因为它不再被引用。但fn的[[范围]]内部属性是什么?或者简单地说,函数对象fn是指记住它是在outer()作用域中创建的吗?好吧,如果您遵循ES5规范,
    internal
    的[[scope]]存储
    outer
    的词法环境,以及它的
    outer
    a
    变量,因此所有内容仍然可以访问和记住。如果遵循实际的ES实现,并使用调试器检查
    内部
    ,则不会看到任何范围引用-它不需要它们,因为没有自由变量。