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

一、内存两大区域:栈内存 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))

相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
伞伞悦读5 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
卡布鲁5 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
C语言小火车5 天前
C/C++ 为什么需要编译器?
开发语言·c++
李少兄5 天前
JavaScript 隐式全局变量解析
javascript