闭包到底是个啥?
平时写代码的时候,你可能没注意,但闭包其实在很多地方悄悄起作用。比如你在 JavaScript 里定义了一个函数,这个函数用了外面函数的变量,哪怕外面那个函数已经执行完了,里面的函数还是能访问那些变量——这就是闭包。
举个生活里的例子:就像你去便利店买饮料,店员把一瓶可乐从冰柜里拿出来交给你,虽然冰柜门已经关上了(相当于外层函数执行完了),但这瓶可乐还是保持着冰的温度。内层函数拿着外层的变量,就像这瓶还凉着的可乐,状态被“封存”了下来。
一个简单的闭包例子
来看一段代码:
function counter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const myCounter = counter();
myCounter(); // 输出 1
myCounter(); // 输出 2
myCounter(); // 输出 3这里 counter 函数执行完后,按理说它的内部变量 count 应该被回收了。但因为返回的那个函数“记住”了 count,所以它一直存在。每次调用 myCounter(),count 都会累加,这就是闭包的核心能力——保留对变量的引用。
闭包能干啥用?
实际开发中,闭包常用来做数据隐藏和封装。比如你不想让别人随便改某个变量,就可以把它藏在外层函数里:
function createBankAccount(initialBalance) {
let balance = initialBalance;
return {
deposit(amount) {
balance += amount;
console.log(`存入$${amount},当前余额$${balance}`);
},
withdraw(amount) {
if (amount <= balance) {
balance -= amount;
console.log(`取出$${amount},当前余额$${balance}`);
} else {
console.log('余额不足');
}
}
};
}
const account = createBankAccount(100);
account.withdraw(30); // 取出$30,当前余额$70
account.deposit(50); // 存入$50,当前余额$120外面根本没法直接访问 balance,只能通过提供的方法操作。这种“私有变量”的效果,在没有 class 私有字段的老版本 JS 里特别有用。
闭包不是什么高深莫测的概念,它就是函数和它所处词法环境的组合。理解了这一点,再看回调、事件处理、防抖节流这些常见模式,就会发现闭包无处不在。