闭包中的变量在不再被任何活跃作用域持有引用时被自动回收;典型不回收场景包括全局变量持有闭包、未移除的dom事件监听器、定时器或缓存结构持续引用,因其使变量保持可达;关键回收条件是闭包本身失去所有外部引用,且无其他路径访问其捕获变量。

闭包中的变量引用会在**不再被任何活跃作用域持有引用**时被自动垃圾回收。
闭包变量不被回收的典型情况
只要闭包函数本身还被某个变量、对象属性或事件监听器等持有引用,它内部捕获的外部变量就无法被回收。这是因为 JavaScript 的垃圾回收基于“可达性”——从全局根(如 window、globalThis)出发能访问到的对象,都被视为“可达”,不会被清理。
- 返回的闭包被赋值给全局变量(如 let fn = outer() ),则闭包及其捕获的变量长期存活
- 闭包作为事件处理器绑定在 DOM 元素上,而该元素未被移除,变量持续驻留
- 闭包被存入数组、Map 或其他数据结构中且该结构未被清空或释放
闭包变量可被回收的关键条件
当闭包函数本身失去所有外部引用,并且没有其他路径能访问到它所捕获的变量时,这些变量就会在下一次垃圾回收周期中被释放。
- 显式将闭包引用设为 null 或重新赋值(如 fn = null),切断根路径
- 闭包仅存在于局部作用域内,且该作用域已退出,又无外部保留(例如:立即执行后未返回、未赋值)
- 使用 WeakMap 或 WeakRef 等弱引用结构间接持有闭包,避免强引用阻碍回收
浏览器实际回收时机不可控但机制明确
现代引擎(如 V8)采用标记-清除算法,定期扫描内存。它会从根对象出发遍历所有可达对象,未被标记的即判定为“不可达”。闭包变量是否被回收,取决于此时是否还有任意一条引用链通向它——和代码写法直接相关,和时间点无关。
- 即使闭包函数已执行完毕,只要它被外部持有着,其词法环境中的变量就仍属“可达”
- 没有循环引用的前提下,解除对闭包的引用后,通常在几毫秒到几百毫秒内完成回收(具体由引擎调度决定)
- 开发者无法手动触发 GC,但可通过 Chrome DevTools 的 Memory 面板手动拍摄堆快照验证回收效果
本质上,闭包变量的生命周期只取决于引用关系是否存在,而不是函数是否执行结束。理清谁在引用闭包,就能预判变量何时释放。











