JavaScript数据类型分栈(基本类型)和堆(引用类型)存储:基本类型值直接存栈,独立复制;引用类型值存堆,栈存地址,多变量可共享同一堆对象。

JavaScript 中的数据类型在内存中分栈和堆存储,核心在于“值怎么存、谁来管、改了影响谁”。基本类型走栈,引用类型走堆,不是凭空规定,而是由数据特性决定的。
基本类型为什么存在栈里
Number、String、Boolean、null、undefined、symbol、BigInt 这 7 种类型,值固定、体积小、生命周期明确。比如 let a = 42,42 直接写进栈里一块确定大小的位置;let b = a,是把 42 这个值完整复制一份,a 和 b 各自独立。函数执行完,这些变量自动消失,系统立刻回收空间。
- 栈内存连续、访问快,适合频繁读写的轻量数据
- 值直接存储,不存在“共享地址”问题
- 短字符串(如
"hi")通常也进栈,引擎会做优化
引用类型为什么必须放堆里
对象、数组、函数、Date、RegExp 等,结构不固定、可能很大、生命周期不确定。声明 let obj = { x: 1 } 时,栈里只存一个指向堆中实际数据的地址(比如 0xabc123);真正 { x: 1 } 这个结构体,存在堆里。
- 堆内存动态分配,能容纳任意大小的对象
- 多个变量可以指向同一个堆地址,所以
let obj2 = obj后,改obj2.x就等于改obj.x - 没有手动释放机制,靠垃圾回收器(GC)标记清除不再使用的对象
栈和堆协作的真实例子
看这段代码:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
function foo() {
let num = 100; // 栈:存值 100
let arr = [1, 2, 3]; // 栈:存地址 → 堆:存 [1,2,3]
let copy = arr; // 栈:再存一次相同地址 → 仍指向堆中同一数组
copy.push(4); // 修改堆里的数组内容
console.log(arr); // [1, 2, 3, 4] —— 因为 arr 和 copy 共享堆地址
}
函数调用时,num、arr、copy 都在栈上分配空间;但只有 arr 和 copy 的“值”是地址,它们共同管理堆里那一块数组内存。
理解偏差容易踩的坑
有人以为“字符串一定在栈”,其实长字符串(比如一段 JSON 文本)V8 引擎可能放进堆;也有人觉得“函数在栈”,但函数体代码和闭包数据都在堆里,栈只存执行上下文和局部变量引用。
- 栈管“快进快出”的临时数据,堆管“可大可久”的复杂结构
- 传参时:基本类型传的是值副本,引用类型传的是地址副本
- 内存泄漏往往发生在堆:比如事件监听器没解绑、定时器没清除,导致堆中对象一直被引用,GC 清不掉
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










