闭包通过外部函数定义变量、内部函数访问修改并返回该函数,实现私有状态封装。典型应用如独立计数器,支持初始化与多操作的状态管理,需注意引用类型陷阱及内存泄漏风险。

闭包可以为函数“记住”并维护私有状态,无需依赖全局变量或外部对象。核心思路是:在外部函数中定义变量,内部函数通过作用域链访问并修改它,返回该内部函数。
用闭包封装计数器状态
最典型的应用是创建独立、可复用的计数器。每次调用外部函数都生成一个新闭包,彼此状态互不干扰。
- 定义外层函数(如 createCounter),内部声明变量(如 count = 0)
- 返回一个内层函数,它读取并更新这个变量
- 调用外层函数得到一个带状态的函数,后续调用持续累加
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter1 = createCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
const counter2 = createCounter();
console.log(counter2()); // 1 —— 独立于 counter1
支持初始化与多操作的状态管理
闭包不仅能记录单一数值,还能承载更丰富的状态和行为。通过返回对象或多个方法,实现类似“实例”的能力。
- 外层函数接收初始参数(如起始值、步长)
- 内部变量保存状态,多个嵌套函数共享同一份数据
- 返回包含 get、increment、reset 等方法的对象
function createCounter(initial = 0, step = 1) {
let value = initial;
return {
get: () => value,
increment: () => { value += step; return value; },
reset: () => { value = initial; return value; }
};
}
const c = createCounter(10, 2);
c.increment(); // 12
c.get(); // 12
避免意外共享状态
闭包状态是私有的,但要注意变量引用陷阱。若闭包捕获的是对象或数组,修改其属性会影响所有引用该对象的闭包。
- 基本类型(number、string、boolean)赋值时复制,安全
- 引用类型(object、array)赋值时传递引用,需深拷贝或重新构造
- 循环中创建闭包时,别直接使用循环变量(如 for (let i...) 更安全,var 会出问题)
实际场景中的轻量状态封装
闭包适合替代简单类或模块,尤其在工具函数、事件回调、配置驱动逻辑中减少冗余代码。
- 防抖函数:闭包保存定时器 ID 和上一次参数
- 缓存函数(memoize):闭包维护 Map 或 Object 存储已计算结果
- 权限校验函数:闭包持有用户角色列表,每次调用检查而不重复传参
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











