🏠 首页 › 攻略 › 闭包是什么?JavaScript函数自带的'记忆能力'

闭包是什么?JavaScript函数自带的'记忆能力'

闭包是JavaScript最核心的概念之一。理解它,你就理解了函数如何'记住'外部变量。

什么是闭包?

闭包(Closure)是JavaScript中一个让很多初学者头疼的概念。但说穿了,它其实很简单:一个函数能"记住"它被创建时所在作用域的环境。

想象你有一个箱子,里面装着几个变量。你把箱子封好,然后把这个箱子交给另一个人。即使这个人离开了你当初放箱子的房间,他打开箱子,依然能看到里面的东西。闭包就是这样一个"箱子"。

用代码来说:

function createCounter() {
  let count = 0; // 这是外部变量
  
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

createCounter 函数执行完了,按理说它的局部变量 count 应该被销毁。但返回的内层函数仍然能访问 count,这就是闭包。

闭包有什么用?

1. 数据私有化

JavaScript没有像Java那样的private关键字,但闭包可以模拟私有变量:

function createBankAccount(initialBalance) {
  let balance = initialBalance; // 外部无法直接访问
  
  return {
    deposit(amount) {
      balance += amount;
      return balance;
    },
    withdraw(amount) {
      if (amount <= balance) {
        balance -= amount;
        return balance;
      }
      return "余额不足";
    },
    getBalance() {
      return balance;
    }
  };
}

const account = createBankAccount(1000);
console.log(account.getBalance()); // 1000
console.log(account.balance); // undefined(无法直接访问)

2. 函数工厂

根据参数动态生成不同的函数:

function makeMultiplier(factor) {
  return function(num) {
    return num * factor;
  };
}

const double = makeMultiplier(2);
const triple = makeMultiplier(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

3. 保存状态

最经典的例子就是计数器,或者分页、定时器管理等需要"记住"状态的场景。

闭包怎么产生?

记住三个条件:

  1. 函数嵌套:一个函数定义在另一个函数内部
  2. 内部函数引用了外部函数的变量
  3. 内部函数被返回到外部作用域使用

三个条件缺一不可。如果内部函数没有引用外部变量,就不会形成闭包。

常见误区

误区一:闭包就是匿名函数

不是。匿名函数只是语法形式,闭包是一种机制。命名函数同样可以形成闭包。

误区二:每次调用都创建新闭包

不对。只要内部函数引用了外部变量,就形成闭包。多次调用同一个函数,每次创建的是新的闭包实例,共享相同的代码但拥有独立的状态。

误区三:闭包很慢

早期浏览器确实有闭包性能问题,但现代JavaScript引擎已经优化得很好了。正常业务场景不需要担心。

总结

闭包的核心就一句话:函数带着它出生时的环境一起行动。

它让你能在JavaScript中实现数据封装、状态保持、函数工厂等强大功能。理解闭包,是理解JavaScript异步编程、模块化设计的基石。

下次看到"为什么这个变量还在"的时候,你就知道——是闭包在起作用。