你对 JavaScript 闭包了解多少?

2025-06-07

你对 JavaScript 闭包了解多少?

当我阅读一些文章,希望从中获得灵感,并为接下来的博客文章寻找新的思路时,我的目光落在了 JavaScript 闭包上。我的第一反应是听说过它,可能也了解它。但当我想象着有人来解释它时,我意识到除了它可能在作用域中关闭某些东西之外,我真的不知道它是什么……所以我回到了基础,阅读文章、文档,观看 YouTube 视频,并在其间玩 PS4 来保持理智。这就是我对这个主题的发现。

但为什么你应该关心学习它

比如面试。如果你能解释最令人困惑的话题之一,那将增强你获得工作的优势。
第二个原因,对我来说更个人化,是 React 框架。React Hook API 和函数式组件很大程度上基于闭包。你将更好地理解 Hook 的运作方式。

那么闭包是什么?

在 JavaScript 中,闭包是指可以访问其周围(父级)作用域的函数。每次创建函数时都会创建闭包。借助闭包,函数可以保存状态或拥有本地(私有)变量,即使在父函数被调用并关闭后,这些变量仍然可以被访问。
让我们来看以下示例:

function outer() {
  const message = "Hello"; // local variable

  function inner() { // a closure function
    return message;
  }

  return inner;
}

const greeting = outer();

greeting() // will return a message "Hello"

这里我们在函数内部有一个message变量outer。它是一个局部变量,无法在父函数外部访问。除非我们inner在父函数内部创建一个闭包函数,否则它可以访问外部作用域和一个变量message。此外,重要的是返回闭包函数而不调用它。
当我们将函数赋值outer给变量时greeting,会发生以下几件事:

  1. outer函数运行一次并返回一个闭包函数;
  2. outer函数自行关闭
  3. greeting变量变成了函数声明,现在可以访问闭包innermessage变量。

现在该greeting函数已成为函数声明,可以调用它,并且返回的结果将是来自该函数的消息outer

考虑到函数被调用一次就自行关闭了,这可能有点奇怪outer。在某些编程语言中,局部变量仅在函数执行的生命周期内存在。但在 JavaScript 中并非如此。在这里,函数创建闭包,其中包含所有周围环境,例如创建时处于作用域内的变量。
greeting函数拥有对闭包函数的引用inner。后者在outer函数执行期间创建,并保存了变量所在的环境message

在哪里可以使用

你可能已经用过它了,只是你不知道,尤其是在使用过 React 框架的情况下。所有函数式组件的事件处理程序都是闭包。
此外,闭包还可以用于模拟函数的私有方法,类似于类方法。例如:

function setCounter() {
  let _counter = 0;

  function changeCounter(value) {
    _counter += value;
  }

  return {
    increment: () => changeCounter(1),
    decrement:() => changeCounter(-1),
    getValue: () => _counter,
  };
}

const counter = setCounter();

counter.getValue() // returns 0
counter.increment()
counter.getValue() // returns 1

在反例中,我们使用闭包incrementdecrementgetValue作为公共函数方法。它们可以访问_counter函数的值。除了这些方法之外,没有其他方法可以访问_counter

让我们构建另一个有状态函数:

function useState(initialValue) {
  let _val = initialValue;

  const state = () => _val;
  const setState = (newValue) => {
    _val = newValue
  };

  return [state, setState];
}

const [count, setCount] = useState(0);

console.log(count()) // returns 0
setCount(5);
console.log(count()) // returns 5

在后一个例子中,我们有两个闭包函数:state一个返回_val变量的当前状态,另一个通过修改变量的值来setState修改_val变量。这是 React useStatehooks 的一个非常原始的实现。

总结

闭包是一个既难又有趣的话题。当我决定学习并撰写关于它的文章时,我并没有意识到它是如此广泛和令人困惑。本文中的示例非常原始且简短,但我希望你能更好地理解它,尤其是函数如何保存状态。

文章来源:https://dev.to/spukas/what-do-you-know-about-javasscript-closures-4725
PREV
采样器。仪表盘、监控和警报——直接在你的终端上。它是如何工作的?示例还有更多!
NEXT
通过构建简单的聊天应用程序学习 WebSockets