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. 延伸阅读

相关推荐
Cache技术分享几秒前
258. Java 集合 - 深入探究 NavigableMap:新增方法助力高效数据处理
前端·后端
Jingyou2 分钟前
JavaScript 实现深拷贝
前端·javascript
编程猪猪侠3 分钟前
Vue 通用复选框组互斥 Hooks:兼容 Element Plus + Ant Design Vue
前端·javascript·vue.js
凡人程序员3 分钟前
搭建 monorepo 项目
前端·javascript
linda26183 分钟前
说说 Map 和 Set 的区别及实际应用
前端·javascript
_一两风4 分钟前
“点一下就能改”——这个功能为首富赚到了多少money?
前端·javascript
小飞侠在吗6 分钟前
vue setup与OptionsAPI
前端·javascript·vue.js
疯不皮6 分钟前
tiptiap3如何实现编辑器内部嵌套多个富文本编辑器
前端·vue.js·开源
溪饱鱼7 分钟前
主动与被动AI交互范式
前端·后端·aigc
我叫黑大帅8 分钟前
如何实现UniApp登录拦截?
前端·javascript·vue.js