← 返回文章列表
JavaScript·1049 次阅读

JavaScript 垃圾回收与常见内存泄漏

JavaScript 垃圾回收与常见内存泄漏

JS 的内存分配和回收是自动的,但"自动"不代表不会泄漏。了解 GC 的工作方式,才能知道泄漏从哪来。

内存生命周期

const arr = [1, 2, 3] // 1. 分配内存
console.log(arr) // 2. 使用
// 3. 不再需要时,由 GC 自动回收

两种回收策略

引用计数(早期方案):记录每个对象被引用的次数,归零就回收。致命缺陷是循环引用——两个对象互相引用,计数永远不为零:

function fn() {
  const a = {}
  const b = {}
  a.ref = b
  b.ref = a
}
fn() // 函数结束后 a、b 都没用了,但引用计数法无法回收

标记清除(现代浏览器主流):GC 从根对象(window/global)出发,把能到达的对象全部标记,没标记到的就是"不可达",一律清除。循环引用只要从根出发不可达,照样回收。

V8 在标记清除基础上还做了分代优化:新生代用 Scavenge(复制算法,频繁小回收),老生代用标记清除+标记整理,减少全量扫描停顿。

四类典型内存泄漏

  1. 意外的全局变量
function fn() { x = new Array(100000) } // 漏写 const,挂到 window 上,永不释放
  1. 被遗忘的定时器 / 事件监听——回调里引用着外部数据,不 clear/remove 就一直活着
  2. 闭包持有——DOM 都删了,闭包还引用着关联数据
  3. 脱离 DOM 的引用——JS 变量缓存了 DOM 节点,节点删除后变量没置 null
const cache = {}
function add(id) { cache[id] = document.getElementById(id) }
add('box')
document.getElementById('box').remove() // DOM 没了,但 cache.box 仍引用,节点无法回收

如何排查

Chrome DevTools → Memory:拍堆快照(Heap snapshot),操作前后对比,看哪些对象只增不减;Performance Monitor 实时看 JS heap size 曲线,只涨不回落就有嫌疑。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4