JavaScript高级:深浅拷贝

目录

1 引言

2 浅拷贝

2.1 拷贝数组

 1.2 拷贝对象

3 赋值操作和浅拷贝的比较

4 深拷贝

4.1 前置知识 --> 递归函数

4.2 使用递归实现深拷贝

4.3 js库中的lodash里面的cloneDeep内部实现深拷贝

4.4 利用JSON实现深拷贝


深浅拷贝只针对引用数据类型

1 引言

假如我们想要使用一个对象,我们之前通常使用赋值的方式,但是使用赋值的方式时,修改赋值后的对象中的数据,会影响原对象!!!

比如:

const obj = {name: '张三',age: 18,
}
console.log(obj)
const obj2 = obj;
obj2.name = '李四'
console.log(obj2)
console.log(obj)


而上述的代码只是修改了简单数据类型,如果修改复杂数据类型结果更是如此了!!!

2 浅拷贝

浅拷贝遇到复杂的数据类型拷贝的是地址

2.1 拷贝数组

方式一:

const arr1 = [1, 2, 3]
const arr = [...arr1]
console.log(arr)
arr[0] = 100
console.log(arr)
console.log(arr1)


方式二:

const arr1 = [1, 2, 3]
const arr2 = arr1.concat()
console.log(arr2)
arr2[0] = 100
console.log(arr2)
console.log(arr1)

以上两种方式可以实现单层数组的拷贝,那么如果我们遇到嵌套的数组,使用这种方式还可以吗? 

例:

const arr1 = [1, [1, 2, 3], 3]
const arr2 = arr1.concat()
console.log(arr2)
arr2[1][2] = 100
console.log(arr2)
console.log(arr1)

此时我们修改拷贝后得到的数组中的数据发现,原数组也被修改了。所以当遇到单层的数组时,拷贝时,数组中只是简单数据类型,修改不会影响原数组,但是如果是嵌套的数据,数组中包含数组,那么拷贝是是直接将内层数组作为一个元素拷贝,数组属于复杂数据类型,所以最终拷贝的是地址


 1.2 拷贝对象

比如以下代码:

const obj = {name: '张三',age: 18,height: 1.88,family: {                        father: '李四',mother: '王五'}
}

方式一:

const o = { ...obj }
console.log(o)
o.name = '李四'
console.log(o)
console.log(obj)


方式二:

const o = Object.assign({}, obj)
console.log(o)
o.age = 20
o.family.father = '赵六'
console.log(o)
console.log(obj)

在上面的这段代码中,我们修改拷贝后的对象中的复杂数据类型,结果如下:


3 赋值操作和浅拷贝的比较

1、直接赋值的方式,只要是对象都会相互影响,因为都是直接拷贝的是栈中的地址。

2、浅拷贝如果是一层对象不会相互影响,如果出现多层对象,还是会相互影响。(因为如果拷贝的对象中是简单数据类型,直接拷贝的是值,如果是复杂数据类型拷贝的还是地址)

--->   浅拷贝在直接赋值的不足之处进行了改进,而浅拷贝同样也是需要改进,接下来将介绍深拷贝,将解决浅拷贝的不足之处

4 深拷贝

4.1 前置知识 --> 递归函数

首先递归函数是什么?简单理解就是自己调用自己。

1 例:实现阶乘

【代码】:

function fn(n) {if (n <= 1)return 1return n * fn(n - 1)
}
const re = fn(5)
console.log(re)

2 案例:利用递归函数实现setTimeout 模拟setInterval效果

【代码】:

function getTime() {document.querySelector('div').innerHTML = new Date().toLocaleString()setTimeout(getTime, 1000)
}
getTime()

4.2 使用递归实现深拷贝

const obj = {name: '张三',age: 18,hobby: ['学习', '喝酒', '烫头'],family: {father: '张三丰',mother: '张三娘'}
}

【需求】:现在需要拷贝上述 obj 对象中的所有数据,并且修改拷贝后的对象,不管修改的是简单数据类型,还是复杂数据类型,都不会影响原对象

const obj1 = {}// 拷贝函数
function deepClone(obj1, obj) {  // onj1是新对象,  obj是旧的for (let key in obj) {// 处理数组的问题if (obj[key] instanceof Array) {obj1[key] = []deepClone(obj1[key], obj[key])} else if (obj[key] instanceof Object) {  // 处理对象的问题  因为arr 也属于对象, 所以判断对象时,写在后面obj1[key] = {}deepClone(obj1[key], obj[key])} else {  // 处理其他数据类型的问题obj1[key] = obj[key]}}
}deepClone(obj1, obj)
obj1.age = 30
obj1.hobby[0] = '睡觉'
console.log(obj1)
console.log(obj)


4.3 js库中的lodash里面的cloneDeep内部实现深拷贝

1. 首先引入lodash.js文件

也可以使用 npm 直接安装

$ npm i -g npm
$ npm i --save lodash

2 【代码】:

const obj = {name: '张三',age: 18,height: 1.88,family: {  // 遇到这种复杂数据类型,拷贝的还是地址, 修改会相互影响father: '李四',mother: '王五'}
}const obj1 = _.cloneDeep(obj)
obj1.family.father = '赵六'
console.log(obj1)
console.log(obj)



虽然使用js自带的库实现深拷贝比递归的方式简单多了,但是还用引入文件也挺麻烦的,接下来再介绍一种更简单的方式。

4.4 利用JSON实现深拷贝

【代码】:

const obj = {name: '张三',age: 18,height: 1.88,family: { father: '李四',mother: '王五'}}const obj1 = JSON.parse(JSON.stringify(obj))  // 先拿到的是字符串,属于简单数据类型,直接存值console.log(obj1)
obj1.family.father = '赵六'
console.log(obj1)
console.log(obj)

注意:JSON.stringify()只能处理对象和数组,不能处理函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/660530.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Windows系统使用Plex部署影音服务与公网访问本地资源【内网穿透】

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通…

人工智能时代:AI提示工程的奥秘 —— 驾驭大语言模型的秘密武器

文章目录 一、引言二、提示工程与大语言模型三、大语言模型的应用实践四、策略与技巧五、结语《AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型》亮点内容简介作者简介目录获取方式 一、引言 随着人工智能技术的飞速发展&#xff0c;大语言模型作为一种新…

如何发布自己的npm包:

1.创建一个打包组件或者库&#xff1a; 安装weback&#xff1a; 打开项目&#xff1a; 创建webpack.config.js,创建src目录 打包好了后发现两个js文件都被压缩了&#xff0c;我们想开发使用未压缩&#xff0c;生产使用压缩文件。 erserPlugin&#xff1a;&#xff08;推荐使用…

UAD155A0111 3BHE029110R0111

UAD155A0111 3BHE029110R0111 UAD155A0111 3BHE029110R0111 UAD155A0111 3BHE029110R0111如何通过CDMA模块实现车载终端数据通信 ... 包括单片机(rabbit2000)、GPS模块、CDMA 手机模块、GSM手机模块、铁电存储器、 ... 提取经纬度信息&#xff0c;通过GSM和 CDMA 模块分别采…

YIA主题如何关闭新版本升级提示?WordPress主题怎么取消升级提醒?

前两天YIA主题发布了升级到2.8版本&#xff0c;新增了一些功能&#xff0c;优化调整修复了一些功能&#xff0c;但是这些功能调整幅度不大&#xff0c;加上boke112百科使用的YIA主题已经进行了很多方面的个性化修改&#xff0c;所以就懒得升级了&#xff0c;但是每次进入WordPr…

Spring的事件监听机制

这里写自定义目录标题 1. 概述&#xff08;重点&#xff09;2. ApplicationEventMulticaster2.1 SimpleApplicationEventMulticaster2.2 AbstractApplicationEventMulticaster 3. ApplicationListener3.1 注册监听器3.2 自定义 4. SpringApplicationRunListeners 1. 概述&#…

Python接口自动化测试(接口状态)

本节开始&#xff0c;开始介绍python的接口自动化测试&#xff0c;首先需要搭建python开发环境&#xff0c;到https://www.python.org/下载python 版本直接安装就以了&#xff0c;建议 下载python2.7.11版本&#xff0c;当然&#xff0c;也是可以下载python最新版本的。 接口测…

纯干货,3步轻松生成智慧乡村3D场景!

临近春节返乡&#xff0c;网上有个话题又重新上了热门&#xff0c;“以你的专业&#xff0c;回到家乡能做什么贡献&#xff1f;”虽然很多人调侃&#xff0c;对家乡最大的贡献就是“离开家乡”&#xff0c;但其实现在农村老家的发展也离不开打工人在远方的支持。 比如AMRT3D引…

Docker基础(持续更新中)

# 第1步&#xff0c;去DockerHub查看nginx镜像仓库及相关信息# 第2步&#xff0c;拉取Nginx镜像 docker pull nginx# 第3步&#xff0c;查看镜像 docker images # 结果如下&#xff1a; REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 60…

【数学】【记忆化搜索 】【动态规划】964. 表示数字的最少运算符

作者推荐 【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数 本文涉及知识点 动态规划汇总 数学 记忆化搜索 LeetCoce964表示数字的最少运算符 给定一个正整数 x&#xff0c;我们将会写出一个形如 x (op1) x (op2) x (op3) x … 的表达式&#xff0c;其中每…

接口性能优化常见12式

目录 1.批处理 2.异步处理 3.空间换时间 4.预处理 5.池化思想 6.串行改并行 7.索引 8.避免大事务 9.优化程序结构 10.深分页问题 11.SQL优化 12.锁粒度避免过粗 1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场…

微服务—Docker

目录 初识Docker Docker与虚拟机的区别 镜像与容器 Docker架构 常见Docker命令 镜像命令 容器命令 数据卷挂载 直接挂载 初识Docker 在项目部署的过程中&#xff0c;如果出现大型项目组件较多&#xff0c;运行环境也较为复杂的情况&#xff0c;部署时会碰到一些问题&…

算法练习-逆波兰表达式求值(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;栈与队列 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c…

Plant, Cell Environment:DNA pull down技术助力揭示AP2/ERF类转录因子提高芍药耐高温能力的分子机制

芍药是一种传统的中药材&#xff0c;并且具有极高的欣赏价值&#xff0c;其生长发育经常受到高温胁迫的影响。褪黑素是一种内源性微分子吲哚胺化合物&#xff0c;在各种生物体中具有多种生理功能&#xff0c;大量研究表明调节与褪黑素生物合成相关的基因来提高植物对高温的耐受…

《区块链简易速速上手小册》第8章:区块链的技术挑战(2024 最新版)

文章目录 8.1 可扩展性问题8.1.1 基础知识8.1.2 主要案例&#xff1a;比特币的可扩展性挑战8.1.3 拓展案例 1&#xff1a;以太坊的可扩展性改进8.1.4 拓展案例 2&#xff1a;侧链和分层解决方案 8.2 安全性与隐私8.2.1 基础知识8.2.2 主要案例&#xff1a;比特币交易的安全性8.…

DVI接口如何连接HDMI接口显示器?DVI转HDMI转换器DHA

DVI转HDMI转换器DHA简介 DVI转HDMI转换器DHA能够将DVI信号和R/L音频信号输入转换成HDMI信号输出,独特的功能使其顺畅地整合到家庭影院中&#xff0c;并且播放出高品质的图像。主要用于数据监控中心、大型会议展示中心、学校及各个公司 DVI转HDMI转换器DHA特点 01.支持分辨率4K…

网络协议 TCP协议

网络协议 TCP协议 文章目录 网络协议 TCP协议1. TCP协议段格式2. 可靠传输保障机制2.1 确认应答2.2 超时重传 3. 连接保障机制3.1 三次握手&#xff08;建立连接&#xff09;3.2 四次挥手&#xff08;断开连接&#xff09;3.3 TCP状态转换过程 4. 传输效率保障机制4.1 滑动窗口…

MySQL原理(二)存储引擎(1)概述

一、存储引擎介绍 1、概念&#xff1a; &#xff08;1&#xff09;MySQL中的数据用各种不下同的技术存储在文件中&#xff0c;每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力&#xff0c;这些不同的技术以及配套的功能在MySQL中称为存储引擎…

【全csdn最前沿LVGL9】按钮的使用(lv_button)、标签的使用(lv_label)

文章目录 前言一、按钮概述二、按钮的使用2.1 创建一个按钮2.2 按钮的样式 三、标签概述四、标签的使用4.1 创建一个标签4.2 样式4.3 设置文本4.4 长文本模式4.5 文本选择4.6 文本对齐4.7 非常长的文本4.8 字体设置字体支持的Unicode字符字体列表特殊的字体 总结 前言 欢迎来到…

Unity使用反向遮罩实现镂空shader

实现步骤&#xff1a; 1&#xff0c;创建两个材质球&#xff0c;遮罩层的属性如下&#xff1a; 被遮罩层的属性如下&#xff1a; 2&#xff0c;使用两张image&#xff0c;遮罩层在父节点&#xff0c;被遮罩层在子节点&#xff0c;然后分别添加材质球与镂空图片 实现效果如下&a…