首页 > 解决方案 > 在 JavaScript 中创建闭包时

问题描述

我想知道在 JavaScript 中创建闭包时

function outerFunc() {
    var a = 2;

    function() {
        console.log(a);
        console.log(b);
    };
    var b = 4;
}

var saveFunc = outerFunc();
saveFunc();

是在执行代码之前创建闭包,还是在调用 outerFunc 时创建闭包,或者在编写 innerFunc 时创建闭包,还是在从 outerFunc 返回 innerFunc 并且将带有闭包的 innerFunc 存储在 saveFunc 中时创建闭包?

标签: javascriptclosures

解决方案


闭包是在函数定义时创建的。所以,如果你有:

var a = 1;
function foo() {
  console.log(a);
}

这是一个关闭。它“关闭”了外部变量。在这种情况下a。老实说,“关闭”对我来说从来没有意义(可能从不同的角度来看),所以我更喜欢这样想 - 一个可以访问外部范围的函数。在这种情况下a来自外部范围。

这可能看起来有点奇怪,因为很多关于闭包的例子和解释都有这样的:

function outer() {
  var a = 1;
  return function inner(b) {//<-----------
    return a + b;           //           |
  }                         //           |
}                           //           |
                            //           |
var add1 = outer();         //           |
                            //           |
console.log(add1.name);     // "inner" ---
console.log(typeof a);      // undefined
console.log(add1(41));      // 42

解释是inner闭包。它在执行后立即创建outer(定义时间inner),然后从outer. 闭包的特殊属性是保留对a当前超出范围的变量的引用。这是真的,但它给人的印象是错误的。函数中不需要外部引用就可以成为闭包。甚至像这样的纯函数

function add(a, b) {
   return a + b;
}

它不使用外部引用并且完全独立,在创建时形成一个闭包。

简而言之,JavaScript 中的任何函数都是一个闭包,而且从来都不是。

但是,这有点学术性。如前所述,闭包的有用属性是它们保留对它们定义的范围的引用。因此,在实践中,我们通常仅在使用此属性时才引用闭包 - 因此,在示例中,innerand outer-形成了闭包,但我们会关注,inner因为它实际上使用了外部作用域。


推荐阅读