闭包本身不会造成内存泄漏,问题在于它被长生命周期对象持续引用而“拽住”DOM节点、大数组等无法回收;需重点排查全局挂载、事件未解绑、定时器未清理、缓存不设限四类高危模式,并用Chrome Memory面板比对快照定位持有者。
闭包本身不会造成内存泄漏,问题出在它无意中“拽住”了不该长期存在的对象。只要闭包被某个长生命周期的东西(比如全局变量、未清除的定时器、还在监听的事件)持续引用,它捕获的外部变量——尤其是 DOM 节点、大数组、组件实例等——就无法被垃圾回收。
不用逐行翻代码,先盯住这四个最常“惹祸”的写法:
window 或模块顶层变量,而它内部又用了 document.getElementById 或大型数据结构;addEventListener 回调,但组件卸载或 DOM 移除后,忘了调用 removeEventListener;setInterval 或 setTimeout 的回调里访问 this、DOM 或响应式状态,却没在销毁时执行 clearInterval;Map 存闭包函数),但没加过期时间、没控制容量、也没用 WeakMap 管理键。打开开发者工具 → Memory 面板,按三步走:
Closure 构造函数,看 Delta 列是否明显增长;window、EventListener、setInterval 或某个 Map 的 entries。不是不用闭包,而是让它轻量、可控、有始有终:
立即学习“Java免费学习笔记(深入)”;
const { id, name } = user; return () => ({ id, name });;useEffect 返回清理函数,Vue 中用 onBeforeUnmount,原生 JS 可维护一个 cleanup 数组统一调用 removeEventListener 和 clearInterval;WeakMap 当缓存容器,节点被移除后,对应条目自动失效,不阻塞 GC。不复杂但容易忽略