JavaScript闭包是什么以及为什么使用它?

JavaScript闭包是函数与其词法作用域变量的组合,能封装私有数据、保持状态上下文、创建定制化函数、实现缓存与惰性计算。

JavaScript闭包是一个函数,加上它能够访问的词法作用域中变量的组合。简单说,就是内部函数记住了自己被定义时所处的外部环境,即使外部函数已经执行完毕、本该销毁,这些变量依然保留在内存中,供内部函数持续使用。

封装私有数据

闭包让变量可以“藏起来”,不被全局或其他代码随意修改。比如计数器场景:

  • 外部无法直接读写 privateCount,只能通过 incrementget 操作
  • 避免命名冲突,也防止意外篡改
  • 这是模块模式和类私有字段(如 #field)出现前最常用的封装手段

保持状态与上下文

在事件监听、定时器、异步回调里,闭包能准确记住每次调用所需的值:

  • 循环绑定点击事件时,每个回调都能记住自己的索引,而不是全变成最后一个 i 值
  • setTimeout 中需要传参?闭包把参数“冻结”进函数体,绕过原生 API 的限制
  • 组件或工具函数中,配置项(如 base URL、重试次数)可一次传入、多次复用

创建定制化函数

闭包支持函数工厂和柯里化,生成行为一致但参数预设不同的函数:

  • add(5) 返回一个“固定加 5”的函数,后续只传第二个数就能算出结果
  • 防抖函数接收 delay 和 callback,返回一个带记忆能力的新函数,每次调用都共享同一组控制逻辑
  • API 请求封装中,createFetcher('/api') 可返回多个专用于该前缀的请求函数

实现缓存与惰性计算

闭包内部可以维护一个缓存对象,避免重复执行高开销操作:

  • 首次调用时计算并存结果,之后直接返回缓存值
  • 适用于格式化、解析、查表等确定性操作
  • 比全局缓存更安全——缓存生命周期与闭包函数绑定,不会污染其他逻辑