

新闻资讯
行业动态JavaScript垃圾回收由引擎自动执行,采用标记-清除算法处理循环引用;WeakMap、WeakRef和FinalizationRegistry可辅助管理弱引用与清理逻辑;常见泄漏源于隐式强引用,需借助DevTools分析保留路径。
JavaScript 的垃圾回收不是你手动控制的,而是引擎自动运行的;它只回收「不再被引用」的对象,不会回收「还有变量指向它」的东西。哪怕你心里觉得“这数据没用了”,只要还存在隐式引用,就不会被收走。
V8、SpiderMonkey、JavaScriptCore 等引擎都用这个基本策略:先标记所有「可访问」的对象(从全局对象、函数调用栈等根集出发遍历引用链),再清除所有未被标记的对象。
a.ref = b 且 b.ref = a,只要 a 和 b 都不再被全局或栈中变量引用,整块内存就会被一并回收IE6 时代因循环引用导致 DOM 对象无法释放的经典内存泄漏delete 或赋值为 null 后内存何时真正释放WeakMap 和 WeakRef 是打破强引用的关键工具
它们允许你持有对象但不阻止 GC 回收——适合缓存、元数据绑定、事件监听器管理等场景。
WeakMap 的键必须是对象,且不阻止该对象被回收;一旦键被回收,对应条目自动消失WeakRef(ES2025)让你拿到一个弱引用句柄,需调用 .deref() 才可能取到原对象;如果已被回收,.deref() 返回 undefined
WeakRef 使用 === 判断是否相等,也不能用它做属性名或 Map 键FinalizationRegistry 可注册回调,在对象被回收后触发清理逻辑(比如关闭底层资源),但不保证立即执行,也不保证一定执行
大多数内存问题不是 GC 失效,而是你不小心维持了本不该存在的引用。
window.cacheData = hugeArray —— 改成局部作用域或显式赋值 cache
Data = null
setInterval(() => {...}, 1000) 中闭包捕获了大对象 → 清理时调用 clearInterval(id),并确保闭包不意外保留对外部作用域的引用addEventListener 后忘记 removeEventListener,尤其在单页应用组件销毁时;推荐用 { once: true } 或用 AbortController 控制信号WeakMap 关联状态,或监听 DOMNodeRemoved(已废弃)/ 使用 MutationObserver
const cache = new WeakMap();
function decorateElement(el) {
if (!cache.has(el)) {
cache.set(el, { timestamp: Date.now(), computedStyle: getComputedStyle(el) });
}
return cache.get(el);
}
// el 被从 DOM 移除后,cache 中对应项会自动消失
真正难调试的从来不是「GC 没运行」,而是「你以为它该被回收,其实还挂着一根看不见的引用」——比如一个被闭包捕获的父级作用域,或者某个第三方库内部保存的回调数组。用 Chrome DevTools 的 Memory 面板拍堆快照,按「Retained Size」排序,点开「Retainers」看谁还在 hold 它,比猜要可靠得多。