优先选闭包:需独立状态、隐藏实现、防抖节流、固定接口;全局变量仅适用于不可变常量、调试标识或宿主环境约定。

闭包和全局变量都能让数据在函数外部被访问,但机制、影响和适用场景完全不同。选哪个,关键看你要不要长期持有数据、是否需要隔离作用域、以及能否接受内存开销。
闭包的核心优势:可控的私有状态
闭包把变量“锁”在函数作用域里,外部无法直接修改,只能通过返回的函数间接操作。
- 避免污染全局命名空间,多个模块互不干扰
- 天然支持封装,比如计数器、防抖定时器、配置缓存等需要维持状态的逻辑
- 变量生命周期由引用决定——只要闭包还存在,变量就留着;闭包被释放,变量才可能被回收
全局变量的典型问题:失控的共享与维护成本
全局变量一定义就在整个脚本生命周期内存在,所有地方都能读写,表面方便,实则隐患多。
- 容易被意外覆盖或误改,尤其在多人协作或引入第三方库时
- 调试困难——某个值变了,你得翻遍所有可能改它的代码
- 无法按需释放,长期占用内存,对单页应用(SPA)尤其不利
什么时候该用闭包而不是全局变量?
满足以下任一条件,优先选闭包:
- 需要为不同实例保存独立状态(比如多个按钮各自维护点击次数)
- 想隐藏实现细节,只暴露有限接口(如
createApi({baseUrl})返回带默认配置的请求函数) - 做防抖、节流、记忆化(memoize)这类依赖上一次执行结果的功能
- 模块初始化后只提供一组固定方法,不需要随时动态增删属性
什么情况下可以考虑全局变量?
极少数场景下,全局变量更直接且合理:
- 真正全局的配置常量(如
const API_ENV = 'prod'),用const声明,不可重赋值 - 浏览器环境下的顶层对象属性(如
window.DEBUG = true),仅用于开发调试且明确知晓风险 - 与 DOM 或原生 API 强绑定的标识(如
document.documentElement.dataset.appVersion),本质是宿主环境约定
实际项目中,95% 的“想用全局变量存点东西”的需求,闭包+模块导出(ESM)或类实例才是更健壮的选择。全局变量不是不能用,而是不该成为默认方案。


















