JavaScript垃圾回收采用标记-清除算法,通过标记可达对象、清除未标记对象来管理内存;常见泄漏场景包括全局变量、未清理定时器/事件监听器、闭包大对象引用及无限制缓存,应分别用严格模式、及时清除引用、精简闭包依赖和WeakMap/LRU策略规避。
JavaScript的垃圾回收(GC)由引擎自动管理,开发者无法手动释放内存,但理解其原理并规范编码习惯,能有效预防内存泄漏。
V8等主流引擎主要采用“标记-清除”(Mark-and-Sweep)算法。它分两步运行:
注意:引用计数曾被早期IE使用,但因无法处理循环引用(如两个对象互相持有对方引用)已被现代引擎弃用。
以下四类问题最易引发泄漏,修复关键在于及时切断不必要的引用:
var/let/const声明变量,会挂载到全局对象(如window),长期存活。✅ 始终启用严格模式("use strict"),避免隐式全局。setTimeout、setInterval或addEventListener未清除,回调函数仍持有所在作用域的引用。✅ 在组件卸载或元素销毁前调用clearTimeout/clearInterval,或使用removeEventListener;对一次性操作优先用AbortController或Promise封装。null。Map或WeakMap(后者对键是弱引用,不阻止GC);为缓存添加大小限制和LRU策略。仅靠经验难以发现隐蔽泄漏,需借助开发者工具:
Array、Object、自定义类);console.memory粗略观察内存趋势;
未释放对象。重点关注“Detached DOM tree”——已从文档移除但仍有JS引用的节点,这是典型泄漏信号。
当必须关联对象又不想阻碍回收时,可用ES6+提供的弱引用机制:
WeakMap:键必须是对象,且为弱引用。当键对象被回收,对应条目自动消失,适合存储元数据或私有属性;WeakRef(ES2025):包装一个对象,不阻止其被回收;需配合deref()安全访问,返回undefined表示目标已回收;WeakSet也存在,但WeakRef不可用于DOM节点(部分浏览器暂不支持)。它们不能解决所有泄漏,但为特定场景提供了更健壮的抽象。