前端中的浅拷贝和深拷贝

news/2024/5/21 12:01:24

话不多说,首先让我们先来看看以下这段代码:

let obj = { num: 1 }
console.log(obj.num)
// 1
let copy = obj
copy.num = 2
console.log(obj.num)
// 2
console.log(obj === copy) // true 完全相等的两个对象

从代码我们可以很清楚的看到obj.num的值发生了变化,但是从表面看,我们似乎并没有对obj进行从操作,为什么会出现这种现象?这就是所谓的浅拷贝引起的。

浅拷贝和深拷贝的理解

首先理解引用类型,引用类型存储地址上存储的是它真正数据存放的地址

换个通俗一点的说法:比如我们去取快递,如果变量是基本类型的话,那我们就是直接去它给我们的地址去取,然而如果是引用类型的话,我们则是去到他给定的地址后拿到一张小纸条,上面写着的才是我们快递所在的真正位置,只有去到纸片上的地址我们才能成功取到我们的快递。

由于对象类型(object, array…)属于引用类型,它在内存上的存储,存储的是它的引用地址(数据真正的存储位置地址),当我们做浅拷贝的操作时,其实就是将这个引用地址赋给另外一个变量,所以最后他们两者拿到的对象是同一个(相当于拷贝的只是那张小纸条)。而深拷贝则是在内存上另外开辟一个位置存储另外一个对象,不过这个对象跟我们所拷贝的对象的数据是一致的。

实现浅拷贝的常用方法

方法1:通过扩展运算符实现

扩展运算符的方式既可以浅拷贝数组(上面已举例),也可以浅拷贝对象,这里我们再举一个浅拷贝对象的例子:

let obj = {a:1,b:2,c:{d:3,e:[1,2]}}let obj1 = {...obj}// 通过扩展运算符浅拷贝,获得对象obj1console.log(obj === obj1)// false,obj和obj1分别指向不同的对象console.log(obj.c === obj1.c)// true,但是obj的c属性的值和obj1的c属性的值是同一个内存地址方法2:通过Object.assign方法实现Object.assign()方法只适用于对象,可以实现对象的合并,语法:Object.assign(target, source_1, ..., source_n).

Object.assign()方法会将source里面的可枚举属性复制到target,复制的是属性值,如果属性值是一个引用类型,那么复制的是引用地址,因此也属于浅拷贝。举例如下:

let target= {name: "小明",}let obj1 = {age: 28,sex: "男",}let obj2 = {friends: ['朋友1','朋友2','朋友3'],sayHi: function (){console.log( 'hi' )},}let obj = Object.assign(target,obj1,obj2)console.log(obj === target) // true,因此可以用变量接收结果,也可以直接使用targetobj1.age = 30 // 把obj1的age属性值改成30console.log("target",target)console.log("obj1",obj1)

我们可以看出返回的结果obj和target都指向浅拷贝的新对象,修改obj1的属性age不会影响target的age属性值。

此时给target的friends属性添加一个新的朋友4,操作如下:

target.friends.push(“朋友4”)

console.log(“target”,target)

console.log(“obj2”,obj2)

此时target的friends属性和obj2的friends属性的值指向同一个数组。

实现深拷贝的常用方法

方法1:通过递归复制所有层级实现

这里我们通过封装一个deepClone函数来实现深层次拷贝,该方法适用于对象或数组,代码如下:

let obj = {name: '小明',age: 20,arr: [1, 2],}function deepClone(value) {// 判断传入参数不是对象或数组时直接返回传入的值,不再执行函数if (typeof value !== 'object' || value == null) {return value}//定义函数的返回值let result// 判断传进来的数据类型数组还是对象,对应创建新的空数组或对象if (value instanceof Array) {result = []} else {result = {}}// 循环遍历拷贝for (let key in value) {//函数递归实现深层拷贝result[key] = deepClone(value[key])}// 将拷贝的结果返回出去return result}let newObj = deepClone(obj)obj.arr[0] = 0 // 修改原对象的arr属性对应的数组的元素值console.log("obj",obj)console.log("newObj ",newObj )

以下是上面代码的打印结果:

我们可以看到深层递归的方式不会复制引用地址,所以用原对象obj修改其arr属性对应的数组的元素,并不会影响新的对象newObj。

方法2:通过JSON对象的stringify和parse方法实现

上面我们讲解深拷贝概念时用过该方法深拷贝数组,这里我们举例来深拷贝对象:

let obj = {name: '小明',age: 20,arr: [1, 2],}let obj1= JSON.parse( JSON.stringify(obj) )console.log(obj.arr === obj1.arr)// false,此时obj的arr属性和obj1的arr属性值不是同一个数组

通过代码我们可以发现,JSON.stringify()方法会把obj先转化为字符串,字符串就已经不代表任何空间地址了,就是单纯的字符串,而JSON.parse()方法把字符串解析成新对象,对象的每个层级都会在堆内存中开辟新空间。

总结

JS的浅拷贝与深拷贝主要是作用于多层级数组或对象中。浅拷贝是只复制创建数组或对象的第一层,其他层级和原数组或对象拥有相同地址值,因此修改浅拷贝的数组或对象的深层的数值就会影响原数组或对象的值。而深拷贝则是拷贝一个全新的数组或对象,每一个层级都在堆内存中开辟了新的空间,和原数组或对象相互不影响。


http://www.mrgr.cn/p/26614342

相关文章

安装了pyintaller后出现:‘pyinstaller‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

2023年7月31日,周一上午 我昨天晚上也遇到了这个问题,后来解决了 目录 出错原因解决方法怎么找到Scripts文件夹 出错原因 出现这个错误是因为你没给python的Scripts文件夹添加环境变量, Scripts存放着pip安装包时产生的可执行文件。 解决…

CentOS下 Docker、Docker Compose 的安装教程

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 Docker Compose是用于定义…

如何启用路由器dhcp?快解析如何内网穿透?

一、什么是DHCP? 动态主机设置协议(DHCP)是一种使网络管理员能够集中管理和自动分配 IP 网络地址的通信协议。在网络中,每个联网设备都需要分配独有的 IP 地址。并当有新计算机移到网络中的其它位置时,能自动收到新的…

百度文心一言接入教程-Java版

原文链接 前言 前段时间由于种种原因我的AI BOT网站停运了数天,后来申请了百度的文心一言和阿里的通义千问开放接口,文心一言的接口很快就通过了,但是文心一言至今杳无音讯。文心一言通过审之后,很快将AI BOT的AI能力接入了文心…

从头学前端-CSS3提升-续

CSS3 2D转换 关键字:transform 移动:沿着x,y轴移动,不会影响盒子的位置,对行内元素没有效果 div {width: 100px;height: 100px;background-color: rebeccapurple;transform: translate(100px,100px);transform: translateX(100p…

TSINGSEE青犀视频安防监控视频平台EasyCVR新增密码复杂度提示

智能视频监控平台TSINGSEE青犀视频EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTM…

孩子近视有必要用全光谱灯吗?全光谱led灯推荐

当然,有必要!全光谱LED灯的光源分布更加均匀,使空间更加美观舒适,而普通灯的光源分布可能会在一定范围内分布不均匀。全光谱它的使用寿命长达20-30万小时,而普通灯的使用寿命仅为1000-2000小时,因此在长期使用上&#…

kettle开发-Day40-AI分流之case/switch

前言: 前面我们讲到了很多关于数据流的AI方面的介绍,包括自定义组件和算力提升这块的,今天我们来学习一个关于kettle数据分流处理非常重要的组件Switch / Case 。当我们的数据来源于类似日志、csv文件等半结构化数据时,我们需要在…

React之组件的生命周期

React之组件的生命周期 一、概述二、整体说明三、挂载阶段四、更新阶段五、卸载阶段 一、概述 生命周期:一个事务从创建到最后消亡经历的整个过程组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程意义:理解组件的生…

Windows环境下git客户端中的git-bash和MinGW64

我们在 Windows10 操作系统下,安装了 git 客户端之后,可以通过 git-bash.exe 打开一个 shell: 执行一些 linux 系统里的命令: 注意到上图紫色的 MINGW64. Mingw-w64 是原始 mingw.org 项目的改进版,旨在支持 Window…

数据安全

数据的备份与恢复 1. 数据备份技术 任何数据在长期使用过程中,都存在一定的安全隐患。由于认为操作失误或系统故障,例如认为错误、程序出错、计算机失效、灾难和偷窃,经常造成数据丢失,给个人和企业造成灾难性的影响。在这种情况…

公网访问的Linux CentOS本地Web站点搭建指南

文章目录 前言1. 本地搭建web站点2. 测试局域网访问3. 公开本地web网站3.1 安装cpolar内网穿透3.2 创建http隧道,指向本地80端口3.3 配置后台服务 4. 配置固定二级子域名5. 测试使用固定二级子域名访问本地web站点 前言 在web项目中,部署的web站点需要被外部访问,则…

TypeScript -- 函数

文章目录 TypeScript -- 函数JS -- 函数的两种表现形式函数声明函数的表达式es6 箭头函数 TS -- 定义一个函数TS -- 函数声明使用接口(定义)ts 定义参数可选参数写法 -- ?的使用TS函数 -- 设置剩余参数函数重载 TypeScript – 函数 JS – 函数的两种表现形式 我们熟知js有两…

python字典:怎么取出key对应的值

目录 python中的字典是什么 怎么判断key是否在字典中 怎么取出key对应的值 总结 python中的字典是什么 在Python中,字典(Dictionary)是一种无序且可变的数据类型,用于存储键-值(Key-Value)对。字典通过…

基于传统检测算法hog+svm实现图像多分类

直接上效果图: 代码仓库和视频演示b站视频005期: 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 代码展示: 数据集在datasets文件夹下 运行01train.py即可训练 训练结束后会保存模型在本地 运行02pyqt.py会有一个可视化…

Element Drawer 抽屉改变默认宽度和高度

Drawer 抽屉 默认宽度为30%&#xff0c;想要改变宽度只需要使用 :size"你需要设置的值" <el-drawer title"我是标题" :visible.sync"drawer" :size"你需要设置的值"><span>我来啦!</span> </el-drawer> dat…

nginx实战

1.nginx简介 1.1 什么是nginx Nginx 是高性能的 HTTP 和反向代理的web服务器&#xff0c;处理高并发能力是十分强大的&#xff0c;能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数。 其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发…

Windows11+Opencv+Clion编译源码

Windows11OpencvClion编译源码 参考&#xff1a;https://www.robotsfan.com/posts/69395e08.html 注意事项 编译过程中使用的软件&#xff0c;开源码等所有工具的安装路径一定不要有中文和空格。cmake过程会下载一些文件&#xff0c;如果是局域网的话可能下载不下来&#xf…

【网络】应用层——HTTP协议

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; &#x1f3c0;认识HTTP协议 上篇文章中&#xff0c;本喵带着大家对HTTP有了一个初步的认识&#xff0…

2023最新ChatGPT商业运营版网站源码+支持ChatGPT4.0+GPT联网+支持ai绘画(Midjourney)+支持Mind思维导图生成

本系统使用Nestjs和Vue3框架技术&#xff0c;持续集成AI能力到本系统&#xff01; 支持GPT3模型、GPT4模型Midjourney专业绘画&#xff08;全自定义调参&#xff09;、Midjourney以图生图、Dall-E2绘画Mind思维导图生成应用工作台&#xff08;Prompt&#xff09;AI绘画广场自定…