一、内存泄漏
1. 什么是内存泄漏?
内存泄漏是指内存被分配但无法被回收的情况。程序中不再使用的变量或对象依然被引用,导致内存占用不断增加,最终可能导致性能下降甚至程序崩溃。
2. 常见内存泄漏场景
-
未清理的全局变量:如果变量未用
var/let/const声明,会成为全局变量,导致内存泄漏。 -
闭包导致的多余引用:闭包引用了外部变量,但这些变量不再需要时,仍无法被回收。
-
DOM 元素未正确释放:删除 DOM 元素后,仍有引用保留,无法释放内存。
-
定时器或回调未清理:
setInterval或异步回调未清理,引用持续存在。 -
事件监听未移除:添加的事件监听器未正确移除,导致内存泄漏。
二、垃圾回收机制
JavaScript 使用自动垃圾回收(GC, Garbage Collection)来释放内存。它会自动查找和清理无用的内存块。
1. 垃圾回收的核心思想
(1) 可达性(Reachability)
一个对象被称为“可达”,如果程序可以通过某些方式访问它:
- 从全局变量访问。
- 被某个闭包或对象引用。
任何无法访问的对象会被标记为“不可达”,随后被清理。
2. 垃圾回收算法
(1) 标记清除(Mark-and-Sweep)
- 是最常用的垃圾回收算法。
- 垃圾回收器会遍历所有对象,标记可达的对象为“活跃”。
- 没有被标记的对象会被释放。
(2) 引用计数(Reference Counting)
- 每个对象维护一个引用计数,当计数为 0 时释放对象。
- 循环引用问题:如果两个对象互相引用,引用计数永远不会为 0。
3. 垃圾回收的触发时机
- 内存占用达到一定阈值。
- 空闲时(浏览器空闲时间会触发 GC)。
三、内存泄漏检测方法
1 使用 Chrome DevTools
步骤:
- 打开 Chrome 开发者工具(
F12)。 - 进入 Memory 面板。
- 使用以下三种选项检测:
- Heap Snapshot:生成当前内存快照,分析对象占用内存。
- Allocation instrumentation on timeline:监控内存分配随时间变化的情况。
- Allocation sampling:采样记录内存分配的热点。
操作步骤:
-
Heap Snapshot 分析:
- 点击
Take Snapshot,生成快照。 - 多次操作后生成快照,对比对象数量和大小是否有异常增长。
- 搜索
Detached DOM,检查是否存在未释放的 DOM 元素。
- 点击
-
观察内存曲线:
- 进入 Performance 面板。
- 点击
Start profiling and reload page。 - 模拟用户操作,观察内存曲线是否持续增长不下降。
2 使用 Lighthouse
- 打开 Chrome 开发者工具。
- 进入 Lighthouse 面板,生成性能报告。
- 检查内存相关的性能优化建议。