javascript垃圾回收机制的核心是自动识别并释放不再可达的对象,由引擎(如v8)基于可达性分析实现:从根对象(如window、局部变量、dom节点等)出发标记所有可访问对象,未被标记的不可达对象在清除阶段被回收;主流算法为标记-清除,v8还采用分代回收优化性能。

可达性决定生死
根对象包括:
• 全局对象(浏览器中是 window,Node.js 中是 global)
• 当前调用栈里的函数局部变量和参数
• 活跃的 DOM 节点(如 document.body)
• 未完成的定时器回调、事件监听器、Promise 状态引用等
例如:
let user = { name: 'Alice', friend: { name: 'Bob' } };<br>user = null;
执行后,原对象无法再从根到达 → 成为垃圾 → 下次 GC 时被清理。
主流算法:标记-清除(Mark-and-Sweep)
这是现代 JS 引擎(V8、SpiderMonkey 等)采用的核心策略,能正确处理循环引用:
- 标记阶段:从根开始遍历所有可到达对象,给它们打上“存活”标记
- 清除阶段:扫描整个堆,回收所有未被标记的对象所占内存
比如两个对象互相引用但脱离根链:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function createCycle() {<br> let a = {}; let b = {};<br> a.ref = b; b.ref = a;<br>}<br>createCycle(); // a 和 b 都不可达 → 标记阶段跳过 → 清除阶段回收
V8 的分代回收设计
V8 把堆内存分为新生代和老生代,按对象“年龄”区别处理:
- 新生代(New Space):存放刚创建的对象,空间小(通常 1–8 MB),用 Scavenge 算法(复制式回收)快速清理短命对象
- 老生代(Old Space):长期存活的对象晋升至此,空间大,用 Mark-Sweep + Mark-Compact 组合:先标记清除,再整理内存减少碎片
对象经历两次新生代 GC 仍存活,就会被晋升到老生代。
哪些情况容易让对象“意外存活”?
这些不是 GC 失效,而是你无意中维持了可达链:
- 全局变量意外挂载(如忘了写 let 或 const,直接赋值)
- 定时器没清理(setInterval 回调持续持有引用)
- DOM 元素已移除,但 JS 对象还保留着对它的引用
- 闭包过度捕获外部大对象(如函数里引用了整个 document 或大数据结构)
- 事件监听器没解绑(尤其动态添加又未移除的)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










