引用类型、内存原理与对象

一、内存两大区域:栈内存 Stack、堆内存 Heap

计算机给 JS 划分两块地方存放数据,分工完全不一样。

  1. 栈内存(Stack)

空间小,读写速度快

存放两类东西:

基本类型的真实值

引用类型的内存地址(编号),不是对象本身!

栈的变量生命周期简单:函数执行完毕、变量失效,直接出栈销毁。

  1. 堆内存(Heap)

空间很大,读写速度比栈慢

只存引用类型真正的数据:对象、数组,一大坨键值对。

最最重要一句话:

引用类型的对象本体永远待在堆;栈里面的变量,只拿着堆的地址编号,相当于门牌号。

举个例子代码:

js

运行

let user = { name: "小明", age: 18 }

内存发生的事情:

JS 在堆内存开辟一块空间,存入完整对象 { name:"小明", age:18 },假设这块堆的地址编号:0xaa01

在栈内存创建变量 user,变量 user 里面不存对象,只存地址 0xaa01

当写 user.name:JS 读取栈中 user 的地址 0xaa01,拿着地址去堆里面找到真实对象,读取 name 属性。

形象比喻:

堆 = 一套真实房子;栈变量 = 写着房子门牌号的小纸条。

user 手里只有纸条(地址),房子本体在堆。访问属性就是拿着纸条去找房子。

二、基本类型 vs 引用类型赋值本质区别

  1. 基本类型:赋值 = 复制一份真实的值(完全拷贝)

js

运行

let a = 100

let b = a

b = 200

console.log(a) // 100

内存过程:

栈:a = 100

let b = a:把 100 这个值复制一份给 b,栈里出现两份独立数据

修改 b=200,只改动 b 自己的数据,a 不受任何影响。

两个完全独立副本,井水不犯河水。

  1. 引用类型:赋值 = 复制地址纸条!不会复制堆里面的对象!

js

运行

let u1 = { name: "小明" }

let u2 = u1

u2.name = "小红"

console.log(u1.name) // 小红

// ② 给变量直接赋全新对象:给u2换一张新门牌号,断开和u1的联系

u2 = { name: "小李" }

①:改房子里面家具 → 所有人看见变化

②:直接换一套新房子,旧房子不受影响。

三、浅拷贝、深拷贝:如何真正产生新对象

需求:不想共用同一个堆对象,想要两个独立对象。

浅拷贝:只复制对象第一层,生成新堆对象;嵌套对象依旧共用地址

js

运行

let obj1 = { a: 10, info: { age: 18 } }

// 浅拷贝写法1:展开运算符

let obj2 = { ...obj1 }

// 浅拷贝写法2 Object.assign

// let obj2 = Object.assign({}, obj1)

内存行为:

堆开辟新对象给 obj2,复制第一层 a:10;

但是里面的 info 是对象,只复制 info 的地址,info 对象还是原来堆里那一个。

js

运行

obj2.a = 999

console.log(obj1.a) //10 第一层互不干扰

obj2.info.age = 999

console.log(obj1.info.age) //999 嵌套对象还是共享堆

浅拷贝只能解决一层,嵌套引用依旧存在。

深拷贝:所有层级全部新建堆对象,彻底切断引用

简单快速方案(局限性:不能拷贝函数、undefined、symbol)

js

运行

let obj2 = JSON.parse(JSON.stringify(obj1))

相关推荐
wuyk5551 小时前
从零吃透 MQTT 通信|第 5 章 MQTT 心跳保活机制深度优化,断线检测与智能自动重连
c语言·开发语言·stm32·学习
jearry1 小时前
给 C++ 老程序补现代 UI:WebView2 多入口资源加载与虚拟主机名实践
前端
Highcharts1 小时前
Highcharts实战讲解|散点图+多项式回归曲线复杂图表示列Demo
javascript·数据可视化
打呵欠的猫1 小时前
让 AI 帮你写 Git Commit Message:从"fix bug"到语义化提交只需一个 Hook
前端·ai编程
labixiong1 小时前
CSS 锚点定位实测:零 JS 实现气泡跟随,自动翻转很香但暗藏 3 个致命坑
前端·css
qibmz1 小时前
用 DeepSeek 给 GitHub 仓库加 PR 自动 Review
前端
计算机魔术师1 小时前
幻觉率从 4.2% 降到 2% 又退回,GPT-6 Astra 到底在藏什么
前端
梨想橙汁1 小时前
Git 常用命令大全:提交、查看日志、版本回退、文件撤销
前端·javascript
weixin_440730501 小时前
socket解决多次输入问题-大数据接收问题-模块动态导入
java·开发语言·servlet