← 返回目录

11. 栈堆内存与引用类型

栈存简单值(数字、字符串、布尔),堆存复杂值(对象、数组)。

核心区别:
基本类型——存在栈里,赋值是复制
引用类型——存在堆里,赋值是复制地址
== 比较——基本类型比值,引用类型比地址

坑:两个内容一样的数组 == 得 false(地址不同)、改一个变量另一个也跟着变(引用类型)

11.1 互动演示(基本类型赋值副本 vs 引用类型共用地址)

点按钮看:基本类型各改各的,引用类型一改全改。

11.2 知识点逐条讲解(配合代码)

① 栈 vs 堆

放什么特点
栈(口袋)数字/文字等小值、还有房门钥匙小、快,函数用完自动清空
堆(小区)对象、数组、函数本体(房子)大,靠垃圾回收定期清理

② 基本类型:= 是复印一份副本

数字、文字、真假这些小东西,直接放在口袋里。写 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);

⑥ X.3 实战:用在哪 / 常见坑 / 怎么解决

① 用在哪:传对象给函数、复制一份配置再改、调试为什么改 A 结果 B 也变了。

② 常见坑:obj2 = obj1 以为复制,结果改一处全变;函数里改对象外面跟着变。

③ 怎么解决:记住对象/数组传的是钥匙;要独立就 {...obj}[...arr] 先复制。

一句话记住:堆=小区放对象本体,栈=口袋放钥匙;基本类型 = 复印副本各改各的;引用类型 = 配把钥匙改一处全变;不想影响原对象就先复制一份

本页重点

API作用参数返回值代码示例
=赋值:基本类型各装各的
let a = 1;

let b = a;  // 复制一份
对象引用多个变量指向同一个柜子改一个全变
let o1 = { n: 1 };

let o2 = o1;  // 同一地址
{...obj}展开复制一份新对象,改它不影响原对象要复制的对象新对象
let copy = { ...obj };  // 真复制