栈存简单值(数字、字符串、布尔),堆存复杂值(对象、数组)。
核心区别:
① 基本类型——存在栈里,赋值是复制
② 引用类型——存在堆里,赋值是复制地址
③ == 比较——基本类型比值,引用类型比地址
坑:两个内容一样的数组 == 得 false(地址不同)、改一个变量另一个也跟着变(引用类型)。
| 放什么 | 特点 | |
|---|---|---|
| 栈(口袋) | 数字/文字等小值、还有房门钥匙 | 小、快,函数用完自动清空 |
| 堆(小区) | 对象、数组、函数本体(房子) | 大,靠垃圾回收定期清理 |
数字、文字、真假这些小东西,直接放在口袋里。写 b = a,就是把 a 的东西复印一份给 b,从此两人各管各的。
let a = 10; // 把10复印一张给b,从此各管各 let b = a; // 改b b = 20; // a还是10,没被影响 console.log(a);
如果你写 obj2 = obj1 以为复印了一个新对象,就会踩坑。因为对象住在堆里,口袋里只放钥匙。= 是又配了一把钥匙指向同一间房。改 obj2 的房里东西,obj1 开门一看也变了。
let obj1 = { name: "橘子" };
// 又配了一把钥匙进同一间房
let obj2 = obj1;
// 用obj2钥匙把名字改了
obj2.name = "猫咪";
// 开门一看也变成"猫咪"
console.log(obj1.name);
function changeName(obj) {
// 拿着传进来的钥匙进房改
obj.name = "修改了";
}
let cat = { name: "小桔子" };
// 把cat的钥匙交给函数
changeName(cat);
// 外面的名字也变成"修改了"
console.log(cat.name);
① 用在哪:传对象给函数、复制一份配置再改、调试为什么改 A 结果 B 也变了。
② 常见坑:obj2 = obj1 以为复制,结果改一处全变;函数里改对象外面跟着变。
③ 怎么解决:记住对象/数组传的是钥匙;要独立就 {...obj} 或 [...arr] 先复制。
| API | 作用 | 参数 | 返回值 | 代码示例 |
|---|---|---|---|---|
| = | 赋值:基本类型各装各的 | 值 | 无 | let a = 1; let b = a; // 复制一份 |
| 对象引用 | 多个变量指向同一个柜子 | 无 | 改一个全变 | let o1 = { n: 1 };
let o2 = o1; // 同一地址 |
| {...obj} | 展开复制一份新对象,改它不影响原对象 | 要复制的对象 | 新对象 | let copy = { ...obj }; // 真复制 |