CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
JavaScript 进阶/课时/内存与 GC
RawBlame
课时目录12 节

JavaScript 进阶

  1. 01JS 进阶地图
  2. 02变量与提升
  3. 03运算符与相等
  4. 04控制流深入
  5. 05函数与 this
  6. 06异步深入
  7. 07对象与原型
  8. 08集合与 JSON
  9. 09模块系统
  10. 10内存与 GC
  11. 11调试与异常
  12. 12综合练习

内存与 GC

memory lifecycle、GC、泄漏排查。

30 分钟

内存与 GC

javascript-core 未涉及运行时内存;本课讲解 内存生命周期、垃圾回收(GC) 与 泄漏排查。长时间运行的 nodejs-essentials 服务与 react-essentials SPA 若泄漏,会表现为卡顿或 OOM。

学习目标

  • 描述 JS 堆内存中对象如何分配与回收
  • 识别常见泄漏模式(全局引用、闭包、定时器、DOM detached)
  • 使用 Chrome DevTools Memory 面板初步定位

内存生命周期

// 1. 分配:声明变量、创建对象
let user = { name: 'Lee', lessons: [] };

// 2. 使用:读写属性
user.lessons.push('jsa-memory');

// 3. 释放:失去所有可达引用后,GC 可回收
user = null;

引擎区分栈(原始值、引用地址)与堆(对象、闭包环境)。

垃圾回收概览

现代引擎(V8)主要用 分代回收 + 标记清除:

新生代(Minor GC)  →  存活对象晋升到老生代
老生代(Major GC)  →  标记存活 → 清除/整理碎片

短生命周期对象(临时变量)在新生代快速回收;长期存活对象进入老生代,Full GC 成本更高。

常见泄漏模式

// 1. 意外全局变量(非 strict)
// leaked = { huge: new Array(1e6) };

// 2. 闭包持有大对象
function createHandler() {
  const bigData = loadHugeCache();
  return () => console.log(bigData.length); // bigData 无法释放
}

// 3.  forgotten 定时器 / 监听器
const id = setInterval(() => {}, 1000);
// 组件卸载时未 clearInterval(id)

// 4. WeakMap 误用为强引用 Map 缓存 DOM
const cache = new Map();
document.querySelectorAll('.item').forEach((el) => {
  cache.set(el, compute(el)); // el 移除 DOM 后 Map 仍强引用
});

修复:组件 cleanup 移除监听、用 WeakMap 关联 DOM、避免无界缓存。

弱引用与 FinalizationRegistry

const wm = new WeakMap();
let obj = {};
wm.set(obj, 'meta');
obj = null; // 条目可被 GC

// FinalizationRegistry(高级,少用于业务)
const registry = new FinalizationRegistry((held) => {
  console.log('GC 了', held);
});

排查步骤

  1. Chrome DevTools → Memory → Heap snapshot(操作前/后各拍一张对比)
  2. 关注 Detached DOM tree、Array 异常增长
  3. Node:node --expose-gc + process.memoryUsage()
function logMem(label) {
  const { heapUsed, heapTotal } = process.memoryUsage();
  console.log(label, Math.round(heapUsed / 1024 / 1024), 'MB');
}

性能习惯

  • 复用大数组时用 .length = 0 或池化,而非频繁 new
  • 事件委托减少监听器数量
  • 分页加载,避免一次 hold 全量列表

练习

  • 写一段未 clearInterval 的泄漏 demo,卸载后观察内存
  • 对比 Map 与 WeakMap 缓存 DOM 节点时的快照差异
  • 在 Node 中打印 process.memoryUsage() 前后差异

小结

失去引用才可 GC;闭包与全局是泄漏温床;DevTools 快照对比定位。 下一课调试与异常。

加载本节练习…
← 上一课模块系统下一课 →调试与异常