原始数据类型存于栈中,引用数据类型的数据存于堆中、地址存于栈中;前者赋值复制值本身,后者赋值复制地址,导致修改相互影响。

原始数据类型存在栈中,引用数据类型的数据存在堆中、地址存在栈中。
原始数据类型:值直接存栈里
String、Number、Boolean、undefined、null、Symbol、BigInt 这 7 种原始类型,变量在栈内存中直接保存具体值。比如:
-
let a = 42;→ 栈中存的就是数字 42 -
let b = "hello";→ 栈中存的就是字符串 "hello" - 赋值时复制的是值本身:
let c = a;,c和a是两个独立的栈空间,互不影响
引用数据类型:地址在栈,数据在堆
Object、Array、Function、Date、RegExp、Map、Set 等都属于引用类型。它们的存储分两步:
- 实际数据(比如对象的属性、数组的元素)存在堆内存中
- 变量本身在栈内存中只存一个指向堆中该数据的地址(指针)
-
let obj1 = {x: 1}; let obj2 = obj1;→obj1和obj2栈中存的是同一个地址,修改obj2.x会影响obj1.x
怎么验证存储位置差异?看赋值和修改行为
不用查内存工具,靠代码表现就能判断:
立即学习“Java免费学习笔记(深入)”;
- 原始类型赋值后互不干扰:
let s1 = "a"; let s2 = s1; s2 += "b"; console.log(s1); // "a" - 引用类型赋值后共享数据:
let arr1 = [1]; let arr2 = arr1; arr2.push(2); console.log(arr1); // [1, 2] -
typeof null返回 "object" 是历史遗留 bug,但不影响它仍是原始类型、仍存在栈中
注意一个常见误解
“存在栈中”不是说 JS 有公开的栈操作 API,而是引擎底层的内存管理机制。开发者感知到的,是值传递 vs 引用传递的行为差异——这正是存储位置不同带来的直接结果。


















