JavaScript中引用类型数据存于堆,变量在栈中仅存指向堆的地址;多个变量可共享同一堆对象,赋值为引用拷贝;垃圾回收基于可达性判断堆内存释放。

JavaScript 中的引用数据类型(如对象、数组、函数、正则、日期等)在内存中确实存放在堆(heap)中,但需要明确的是:变量本身并不直接存储整个对象,而是存储一个指向堆中实际数据的内存地址(即引用)。这个地址被保存在栈(stack)中——也就是说,栈里存的是“指针”,堆里存的是“真实数据”。
堆内存负责存储实际的引用值
当你创建一个对象时,例如:
let obj = { name: "Alice", age: 30 };JavaScript 引擎会做以下几件事:
- 在堆内存中开辟一块连续空间,存放该对象的键值对数据(包括属性名和对应的值);
- 生成一个唯一的内存地址(比如 0x1a2b3c),指向这块堆空间;
- 把该地址赋给变量 obj,而 obj 本身存在栈中(如果是局部变量)或全局环境记录中(如果是全局变量)。
多个变量可以引用同一块堆内存
因为变量只保存地址,所以赋值时是“拷贝引用”,不是拷贝数据:
立即学习“Java免费学习笔记(深入)”;
let a = { x: 1 };let b = a; // b 得到的是 a 指向堆的同一个地址
此时 a 和 b 都指向堆中同一片对象区域。修改 b.x = 2,a.x 也会变成 2。
垃圾回收机制依赖引用关系判断是否释放堆内存
当一个对象不再被任何变量(或闭包、作用域链中的其他引用)所指向时,它就成为“不可达对象”。JavaScript 的垃圾回收器(如 V8 的 Orinoco)会在合适时机自动释放其占用的堆内存:
- 如果执行 a = null; b = null;,且没有其他引用指向该对象,那么它会被标记为可回收;
- 循环引用在现代引擎中通常也能被正确识别并回收(V8 使用可达性算法,而非简单的引用计数)。
注意:原始类型和引用类型的存储位置对比
原始类型(string、number、boolean、null、undefined、symbol、bigint)值小且固定大小,直接存在栈中;而引用类型值大小不固定、可能很大,必须放在堆中动态分配。这种分工既保证了栈的高效访问,又支持了灵活的数据结构。


















