闭包是内部函数持续访问外部函数变量的机制;需满足三条件:外部函数定义变量、内部函数在其中定义、外部函数返回该内部函数;变量为引用而非拷贝,循环中应使用let避免共享变量。

闭包的核心机制就是:内部函数即使在外部函数执行完毕后,仍能持续访问并操作外部函数作用域中的变量。
闭包形成的必要条件
要让内部函数访问外部变量,需同时满足三个条件:
- 外部函数定义了一个变量(或参数)
- 内部函数在外部函数内被定义(不是全局声明)
- 外部函数返回了这个内部函数(或以其他方式使内部函数在外部可调用)
典型写法:返回函数并保留变量引用
这是最常见也最清晰的闭包实现方式:
示例:function createCounter() {
let count = 0; // 外部函数的局部变量
return function() {
count++; // 内部函数直接读写 count
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
这里 count 并未被销毁,而是被返回的匿名函数“捕获”并持续持有——这就是闭包。
立即学习“Java免费学习笔记(深入)”;
变量不是拷贝,而是引用原始绑定
内部函数访问的是变量本身,不是值的副本。如果外部变量是对象,修改其属性也会反映在内部函数中:
function createUser(name) {
const user = { name, age: 0 };
return {
grow() { user.age++; },
getInfo() { return user; }
};
}
const u = createUser("Alice");
u.grow();
console.log(u.getInfo()); // { name: "Alice", age: 1 }
user 是一个对象引用,内部方法共享同一份数据。
注意:循环中使用闭包容易误用变量
常见陷阱是 for 循环中直接创建函数,导致所有内部函数共用同一个变量(如 var i):
✅ 正确做法(用 let 声明,块级作用域):
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出 0, 1, 2
}
❌ 错误写法(var 提升,共享一个 i):
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出 3, 3, 3
}
本质仍是闭包在起作用,只是变量绑定的粒度不同。


















