JavaScript垃圾回收方法
JavaScript 的垃圾回收机制(Garbage Collection, GC)自动管理内存,开发者无需手动分配和释放内存。其核心方法如下:
1. 主要垃圾回收算法
(1) 标记-清除(Mark-and-Sweep)
- 原理:从根对象(如全局变量、活动函数调用栈)出发,标记所有可达对象,清除未标记的对象。
- 优点:解决循环引用问题。
- 流程:
- 标记阶段:遍历对象图,标记所有可达对象。
- 清除阶段:回收未被标记的内存。
- 示例:
let objA = { ref: null }; let objB = { ref: null }; objA.ref = objB; objB.ref = objA; // 即使 objA 和 objB 互相引用,若无法从根访问,仍会被回收。
(2) 引用计数(已淘汰)
- 原理:记录每个对象的引用次数,归零时回收。
- 缺点:无法处理循环引用。
function createCycle() { let x = {}; let y = {}; x.ref = y; y.ref = x; // 循环引用,引用计数无法归零。 }
2. 分代回收(Generational Collection)
现代引擎(如 V8)将对象分为两代,针对不同生命周期优化回收效率。
(1) 新生代(Young Generation)
- 特点:存放短期存活对象(如局部变量)。
- 算法:Scavenge 算法(复制算法)。
- 将内存分为
From和To两个半空间。 - 存活对象从
From复制到To,然后清空From。 - 晋升:多次存活的对象移至老生代。
- 将内存分为
(2) 老生代(Old Generation)
- 特点:存放长期存活对象(如全局变量)。
- 算法:标记-清除 + 标记-整理(减少内存碎片)。
3. 优化策略
(1) 增量标记(Incremental Marking)
- 原理:将标记过程拆分为多段,穿插在主线程任务中执行,减少长时间停顿。
- 适用场景:大型应用避免界面卡顿。
(2) 空闲时间回收(Idle-time GC)
- 原理:在浏览器空闲时段触发垃圾回收。
- 实现:通过
requestIdleCallback调度。
(3) 并行/并发回收
- 并行:多个辅助线程同时执行垃圾回收。
- 并发:主线程运行应用逻辑,辅助线程执行回收。
4. V8 引擎的垃圾回收
- 新生代:使用 Scavenge 算法,快速回收短期对象。
- 老生代:组合使用标记-清除(回收垃圾)和标记-整理(整理内存碎片)。
- 全停顿(Stop-The-World):老生代回收时可能短暂阻塞主线程。
5. 开发者注意事项
(1) 避免内存泄漏
-
意外全局变量:
function leak() { leakedVar = 'This is a global'; // 未用 let/const/var 声明! } -
未清理的引用:
- 定时器、事件监听器、闭包保留的 DOM 引用。
// 错误示例 let element = document.getElementById('button'); element.addEventListener('click', onClick); // 若 element 移除后未取消监听,回调函数仍被引用。
(2) 手动解除引用
- 不再使用的对象设为
null,加速回收:let data = loadHugeData(); // 使用完毕后 data = null;
(3) 使用内存分析工具
- Chrome DevTools:
- Memory 面板:生成堆快照(Heap Snapshot),对比内存变化。
- Performance 面板:监控内存分配趋势。
- Node.js:使用
--inspect标志和 Chrome DevTools 调试。
6. 示例:内存泄漏检测
// 模拟内存泄漏(未清理的数组)
let leaks = [];
setInterval(() => {
leaks.push(new Array(1000000).fill('*'));
}, 1000);
// 在 Chrome DevTools 的 Memory 面板中:
// 1. 拍摄堆快照。
// 2. 多次操作后拍摄第二个快照。
// 3. 对比快照,查找未被回收的数组。
总结
| 机制 | 核心方法 | 场景 | 优化手段 |
|---|---|---|---|
| 新生代回收 | Scavenge 算法(复制) | 短期存活对象 | 快速清理,晋升长期对象 |
| 老生代回收 | 标记-清除 + 标记-整理 | 长期存活对象 | 减少碎片,增量标记 |
| 开发者要点 | 避免循环引用、及时解除引用 | 防止内存泄漏,提升性能 | 使用工具分析,合理设计代码 |
理解垃圾回收机制有助于编写高效、稳定的 JavaScript 代码,避免内存问题导致的性能下降或崩溃。
更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github