堆快照前后对比是排查内存泄漏最直接可靠的方法,需在页面空闲时手动GC后拍Baseline快照,执行操作闭环后再GC拍After快照,通过Comparison模式分析新增对象、Size Delta及Detached节点,并沿Retainers链定位未清理的引用源,修复后需多轮验证是否消除增长。

前端性能调优中排查内存泄漏,堆快照前后对比是最直接、最可靠的方法。关键不是拍得多,而是拍得准、比得清、追得深——重点识别那些本该被回收却持续驻留的对象。
拍两个有逻辑关系的快照
不要在页面刚加载完就拍,也不要操作中途随意抓取。标准流程是:
- 等页面完全空闲(无定时器运行、无动画、无 pending 请求),手动触发一次垃圾回收(点击 Memory 面板左上角垃圾桶图标),再拍第一张快照,标记为 “Baseline”
- 执行一次完整操作闭环(例如:打开弹窗 → 点击确认 → 关闭弹窗),等待 2–3 秒让异步逻辑结束,再次手动 GC,立即拍第二张快照,标记为 “After”
- 重复同样操作 3–5 次后,再 GC 并拍第三张,用于验证增长是否线性
用 Comparison 模式聚焦增长对象
选中 “After” 快照 → 切换到 Comparison 视图 → 选择 “Baseline” 作为对比基准。此时重点关注:
- # New > 0 且构造函数名是你业务代码里的类(如 TableManager、ChartRenderer)或匿名闭包(closure)
- Size Delta > 0,说明不仅数量增加,实际占用内存也在涨
- Detached HTMLDivElement 或 Detached EventListener 类型反复出现——DOM 节点已从文档移除,但 JS 仍持有引用
顺着 Retainers 找强引用源头
点击可疑构造函数(比如 MyComponent),右侧打开 Retainers 标签页,从下往上读引用链:
- 底部是目标对象,顶部通常是 GC root(如 window、document、setTimeout 回调)
- 中间某一层若出现未清理的 addEventListener、全局变量(如 window.cache)、未清除的 setInterval 或缓存 Map,大概率就是泄漏点
- 特别注意路径中出现的模块名或变量名(如 pendingTasks、eventBus.listeners),它们常是“看似无关实则致命”的中间持有者
验证修复是否真正生效
改完代码后不能只看单次对比结果,要闭环验证:
- 用相同操作步骤再跑 3–5 轮,每轮 GC 后都拍快照并做 Comparison
- 确认该构造函数的 # New 基本为 0,或仅波动在 1–2 个(属正常抖动)
- 观察整体 JS heap size 是否趋于平稳,不再随操作次数持续上升
- 如果 retaining path 中仍有你的模块名,但终点已变成 WeakMap 或明确调用了 removeEventListener,说明引用已被正确解除
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











