返回

前端小白也能秒懂闭包!

前端

闭包的前世今生

想象一下,你有一个朋友叫 Alice,她是一个资深的前端开发者。有一天,她兴冲冲地跑来跟你说:“嘿,我发现了一个神奇的东西,叫闭包!”

你一脸懵逼:“闭包?那是啥?”

Alice 耐心解释道:“闭包就是一种 JavaScript 函数,它可以访问其创建时的所有变量,即使这些变量已经超出了它的作用域。”

你挠了挠头:“这有什么特别的?”

Alice 笑道:“别急,听我讲个故事。”

小明和闭包的奇遇

小明是一个 JavaScript 新手,他正在编写一个函数来计算购物车的总金额。

function calculateTotal(cart) {
  let total = 0;
  for (let item of cart) {
    total += item.price;
  }
  return total;
}

乍一看,这个函数似乎没什么问题。但是,小明遇到了一个棘手的情况:当他调用 calculateTotal() 函数时,返回的总金额总是 0。

小明百思不得其解,他仔细检查了代码,发现问题出在 total 变量上。虽然 total 是在函数内部声明的,但它是一个局部变量,只在函数执行期间存在。当函数执行完毕,total 变量也会被销毁。

console.log(total); // 报错:ReferenceError: total is not defined

小明意识到,如果他想在函数外访问 total 变量,就必须想办法让它“活”下来。

这时,小明想起了闭包。他将 calculateTotal() 函数改写成了一个闭包:

const calculateTotal = (cart) => {
  let total = 0;
  for (let item of cart) {
    total += item.price;
  }
  return () => {
    return total;
  };
};

这个闭包函数返回了一个匿名函数,这个匿名函数可以访问 total 变量,即使它已经超出了 calculateTotal() 函数的作用域。

现在,小明可以随时调用这个匿名函数来获取购物车的总金额:

const getTotal = calculateTotal([
  { price: 10 },
  { price: 20 },
  { price: 30 },
]);

console.log(getTotal()); // 60

闭包的应用场景

闭包的应用场景非常广泛,这里列举几个常见的例子:

  • 状态管理: 闭包可以用来存储和管理组件或应用程序的状态。
  • 事件监听器: 闭包可以用来创建事件监听器,即使事件源已被销毁。
  • 缓存: 闭包可以用来创建缓存函数,以避免重复计算。
  • 私有变量: 闭包可以用来创建私有变量,从而隐藏实现细节。

总结

闭包是一种强大的 JavaScript 特性,它允许函数访问其创建时的所有变量。虽然闭包有时会带来复杂性,但它在许多场景中提供了强大的功能。对于前端小白来说,理解闭包的原理至关重要,这将有助于他们编写更健壮、更灵活的代码。