JavaScript 内存管理是如何工作的?

1. 开场白:看不见的房间管家

写 JS 的你我,几乎从不手动 malloc/free,但这不代表内存管理"不存在"。

JavaScript 引擎就像一位房间管家

  • 你买东西(创建变量)→ 管家帮你找空位;
  • 你用完扔一边(解除引用)→ 管家扫进垃圾桶;
  • 你若一直占着茅坑不拉屎(内存泄漏)→ 管家也无可奈何。

理解管家的工作方式,才能让应用不爆内存、不卡顿、不 OOM


2. 两张图看懂"东西"放哪儿

存储区域 放什么 特点 生命周期
Stack 原始值(numberbooleanundefinednullstringsymbolbigint 固定大小、后进先出、超快 函数 return 即自动弹栈
Heap 引用值(ObjectArrayFunctionDateRegExp...) 动态大小、可按引用共享、稍慢 靠垃圾回收器(GC)稍后清理

代码示例

js 复制代码
let age  = 18;        // 栈
let user = {age};     // 栈里只存指针,实际对象在堆

3. 垃圾回收三部曲

现代引擎默认采用**"标记-清除"(Mark-and-Sweep)算法,配合"分代回收"**优化。

3.1 标记阶段(Mark)

从一组**根(Roots)**出发:

  • 当前调用栈里的局部变量;
  • 全局对象(windowglobalThis);
  • 被 Chrome DevTools 断点 Hold 住的变量...

把所有能访问到的对象打上 "在用" 标签,其余都是 "垃圾"

3.2 清除阶段(Sweep)

线性扫堆,把没标签的对象直接释放;

内存空隙由空闲链表按页压缩整理,避免碎片化。

3.3 分代优化(Generational GC)

V8 把堆再细分为:

  • 新生代 (1~8 M):短命对象,采用 Scavenge(复制回收),频率高、停顿短;
  • 老生代 :多次幸存的大对象、长寿命对象,采用 Mark-Sweep + Mark-Compact,频率低、停顿长。

实测:95% 的对象 20ms 内就死,分代后 GC 吞吐量提升 5~10 倍。


4. 四种常见内存泄漏与排查清单

泄漏场景 代码味道 修复要点
1. 意外全局变量 function f(){ leaky="oops" } 'use strict' + ESLint no-undef
2. 忘记清理定时器 setInterval(()=>{...},1000) const t=setInterval(...); 卸载时 clearInterval(t)
3. 闭包捕"大"不放 return ()=>console.log('hi') 却捕获了 new Array(1e6) 只把必要变量闭进去,或手动 largeData=null
4. 游离 DOM + 监听器 removeChild(node) 后仍保留 node 引用 node.remove(); node=null; 同时 off() 监听器

5. 开发者必备:Chrome DevTools 三板斧

  1. Performance Monitor
    实时折线图:JS heap size、DOM 节点、事件监听器数量。
  2. Heap Snapshot
    对比两次快照,按 "Retained Size" 排序,轻松找出"大胃王"。
  3. Allocation Timeline
    录制 30 秒用户操作,蓝色竖线表示新生代分配,峰值即潜在泄漏点。

6. 进阶:WeakMap / WeakRef 让 GC 更聪明

  • WeakMap 只保存弱引用,键对象被回收时,映射条目自动消失;
  • WeakRef 允许你观察对象是否已被 GC,而不阻止其被回收;
  • 适合缓存、DOM 元数据映射,不增加额外可达路径

7. 一句话总结

JavaScript 帮你扫地,但别把垃圾藏到床底 ------

理解栈/堆、标记-清除、分代模型,善用 DevTools,远离四种泄漏,

你的页面才能常驻 60 FPS、不爆 256 M 低端机


8. 延伸阅读

相关推荐
wearegogog1234 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars4 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤4 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·4 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°4 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854055 小时前
CSS动效
前端·javascript·css
烛阴5 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪5 小时前
markstream-vue实战踩坑笔记
前端
南村群童欺我老无力.6 小时前
Flutter应用鸿蒙迁移实战:性能优化与渐进式迁移指南
javascript·flutter·ci/cd·华为·性能优化·typescript·harmonyos
C_心欲无痕6 小时前
nginx - 实现域名跳转的几种方式
运维·前端·nginx