JavaScript中原始类型(number、string等七种)值本身全存栈,赋值复制副本;引用类型变量名和地址存栈,真实数据全在堆,多变量可共享同一堆对象。

JavaScript 中堆与栈的分配,核心不在于“哪些原始类型进栈、哪些进堆”,而在于所有原始类型都只在栈中存储值本身,没有原始类型会进入堆。引用类型则不同:变量名和引用地址存栈,真实数据一定在堆。
原始类型全部驻留在栈中
包括 number、string、boolean、null、undefined、symbol、bigint 这七种。它们共同特点是:
• 值大小固定,编译期可确定所需空间
• 直接写入当前执行上下文的栈帧(如函数调用时的局部变量区)
• 赋值时复制的是值的完整副本,不是地址
• 修改变量只是覆盖栈中对应位置的旧值,不影响其他变量
例如:
let a = 100; let b = a; a = 200; → b 仍是 100,因为 b 拥有独立的一份拷贝,二者内存互不关联。
引用类型的数据本体全在堆中
包括 object、array、function、date、regexp、map、set 等所有对象类结构。它们的存储分两层:
• 栈中只存一个轻量级的引用(即内存地址)
• 对象的实际属性、方法、元素等内容,全部分配在堆内存
• 多个变量可持有同一地址,因此修改对象属性会影响所有引用者
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
例如:
let obj1 = { x: 1 }; let obj2 = obj1; → obj2.x = 99; 后,obj1.x 也变成 99,因为两者指向堆中同一个对象块。
栈和堆的关键区别不只是“存什么”,更是“怎么管”
• 栈由操作系统自动管理:按函数调用压入/弹出,速度快、空间小(Chrome 约 1–2 MB),超深递归易触发栈溢出
• 堆由 JavaScript 引擎(如 V8)自主管理:动态分配、空间大,但依赖垃圾回收(GC)判断可达性来释放内存
• 闭包中的变量可能被提升到堆:即使原本是原始类型,若被闭包长期捕获且外部仍可访问,V8 会将其从栈移至堆以延长生命周期
• const 不改变存储位置:它只禁止重新赋值操作,对原始类型锁住值,对引用类型锁住地址(对象内部仍可修改)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










