JavaScript 中的闭包

2025-06-07

JavaScript 中的闭包

闭包是很多新开发者似乎都难以理解的概念之一。我自己就是其中之一。在这篇文章中,我将尝试通过解决我最初学习闭包时忽略的一个问题:数据持久化,来让这个神秘的概念不再那么神秘。

MDN 对闭包的官方定义如下:“闭包是将函数与其周围状态(词法环境)的引用捆绑在一起(封装)而成的组合。换句话说,闭包允许你从内部函数访问外部函数的作用域。在 JavaScript 中,每次创建函数时,都会创建闭包,即在函数创建时。”

JS 中的闭包有三个主要特征:

  • 一个函数必须返回另一个函数
  • 内部函数可以访问外部函数的变量
  • 外部函数的变量值被保留

让我们看一个闭包示例:

function parentFunc() {
    var counter = 0;

    function childFunc(){
      let innerCounter = 0;
      innerCounter++;
      counter++;
      console.log(counter, innerCounter);
    }

    return childFunc;
}

const myChild = parentFunc();
myChild();
Enter fullscreen mode Exit fullscreen mode

在上面的代码片段中,我们有一个名为 的函数parentFunc(),它返回其嵌套函数childFunc()parentFunc()var counter设置为 0。childFunc()将设置为 0,它将var innerCounter都递增,然后记录两者。我们将 设置为等于执行的counterinnerCounterconst myChildparentFunc()

上述代码的输出为:

1 1
Enter fullscreen mode Exit fullscreen mode

很简单吧?
如果我们执行myChild()多次会怎么样?

function parentFunc() {
    var counter = 0;

    function childFunc(){
      let innerCounter = 0;
      innerCounter++;
      counter++;
      console.log(counter, innerCounter);
    }

    return childFunc;
}

const myChild = parentFunc();
myChild();
myChild();
myChild();
Enter fullscreen mode Exit fullscreen mode

现在的输出是:

1 1
2 1
3 1
Enter fullscreen mode Exit fullscreen mode

在常规函数中,一旦执行完毕,数据就会被清除,不会保留任何数据。
然而,使用闭包时,内部函数会将外部函数的变量存储在其自己的特殊位置,我们可以将其想象成一个背包。外部函数执行后,其内部的数据会被清除,但内部函数会将这些数据存储在其背包中,方便其取用。需要注意的是,它只将来自 parentFunc() 的变量存储在背包中,其自身的变量innerCounter会被视为常规函数,并在执行后被清除。

childFunc()var counter函数执行完毕后,该值将保持不变。这意味着,在第二次执行开始时var counter,该值不会设置为 0,而是设置为 1;在第三次执行开始时,var counter该值设置为 2。

当我们想要记住函数中的某些值时,使用闭包是一个很好的选择。

结论

JS 中的闭包有三个主要特征:

  • 一个函数必须返回另一个函数
  • 内部函数可以访问外部函数的变量
  • 外部函数的变量值被保留

闭包是 JavaScript 中比较微妙的概念,乍一看可能有点难懂。但一旦你深入理解了闭包的三个主要特性,你就会发现它们其实并没有那么有争议。

希望这篇文章能帮助您更好地理解 JavaScript 中闭包的概念!

文章来源:https://dev.to/mariaverse/closures-in-javascript-3289
PREV
React 的 Lottie 动画
NEXT
成为一名开发人员是什么感觉?(动图)🗿