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

相关推荐
jiayong2313 分钟前
第 8 课:开始引入组合式函数
前端·javascript·学习
田八16 分钟前
聊聊AI的发展史,AI的爆发并不是偶然
前端·人工智能·程序员
zhanghongbin0127 分钟前
AI 采集器:Claude Code、OpenAI、LiteLLM 监控
java·前端·人工智能
IT_陈寒32 分钟前
Python的列表推导式里藏了个坑,差点让我加班到凌晨
前端·人工智能·后端
吴声子夜歌40 分钟前
ES6——正则的扩展详解
前端·mysql·es6
天若有情6731 小时前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
天***88521 小时前
Edge 浏览器离线绿色增强版+官方安装包,支持win7等系统
前端·edge
漫游的渔夫1 小时前
别再直接 `json.loads` 了!AI 返回的 JSON 坑位指南
前端·人工智能
软件工程师文艺1 小时前
从0到1:Claude Code如何用React构建CLI应用
前端·react.js·前端框架
M ? A2 小时前
Vue 迁移 React 实战:VuReact 一键自动化转换方案
前端·vue.js·经验分享·react.js·开源·自动化·vureact