对浅拷贝的理解

问题背景

我之前一直以为浅拷贝出来的新对象和旧对象的引用地址是相同的,但是通过Object和===发现浅拷贝的新对象和旧对象的引用地址不同!!

   const obj1 = { name: "Alice", test: { age: 12 } };const obj4 = Object.assign({}, obj1); // 浅拷贝obj4.name = "hhh";obj4.test.age = 99;console.log("obj1", obj1);console.log("obj4", obj4);const obj2 = { name: "Alice" };const obj3 = obj1;console.log(Object.is(obj1, obj2)); // false,因为它们的引用地址不同console.log(Object.is(obj1, obj3)); // true,因为它们指向同一个对象console.log(Object.is(obj1, obj4)); // false!!!console.log(obj1 === obj2); // falseconsole.log(obj1 === obj3); // trueconsole.log(obj1 === obj4); // false!!!

甚至当对象不止一层的时候,也是引用对象不同
因为我一直以为不止一层,那么浅拷贝就直接拷贝地址,那么引用地址总应该相同了吧,唉

   const obj5 = {test: { age: 12 } };const obj6 = Object.assign({}, obj5); // 浅拷贝console.log(Object.is(obj5, obj6)); // false!!!console.log(obj5 === obj6); // false!!!

还是有疑问

既然浅拷贝出来的对象引用地址不同,为什么obj1.test.age也修改了

const obj1 = { name: "Alice", test: { age: 12 } };const obj4 = Object.assign({}, obj1);obj4.name = "hhh";obj4.test.age = 99;console.log("obj1", obj1);console.log("obj4", obj4);

这是因为浅拷贝只会复制对象的第一层属性,而不会递归复制对象中嵌套的对象。所以虽然 obj1 和 obj4 是两个不同的对象,但它们的 test 属性引用的是同一个对象

   console.log(Object.is(obj1.test, obj4.test)); // true!!!console.log(obj1.test === obj4.test); // true!!!

修改 obj4.test.age 实际上修改了 test 属性指向的对象,因此 obj1 中的 test 属性也会受到影响。

要解决这个问题,你需要使用深拷贝而不是浅拷贝。深拷贝会递归地复制对象及其所有嵌套的对象,确保所有对象都是独立的,没有共享引用。

在插一句

    const obj7 = { name: "Alice" };const obj8 = Object.assign({}, obj7); // 浅拷贝console.log(Object.is(obj7.name, obj8.name)); // trueconsole.log(obj7.name === obj8.name); // true

在这段代码中,obj7 和 obj8 中的 name 属性都是字符串,它们的值是相同的,因此 Object.is(obj7.name, obj8.name) 和 obj7.name === obj8.name 都会返回 true。

需要注意的是,这里的比较并不是比较两个对象的引用地址,而是比较它们的值。在 JavaScript 中,字符串是基本数据类型,比较时会直接比较它们的值。
要判断两个字符串的引用是否相同,可以使用严格相等运算符(===)或 Object.is() 方法进行比较。这会比较字符串的引用地址是否完全相同。

const str1 = "hello";
const str2 = "hello";
const str3 = new String("hello");console.log(str1 === str2); // true,直接量相同
console.log(str1 === str3); // false,str3 是一个对象,与 str1 的引用不同
console.log(Object.is(str1, str2)); // true
console.log(Object.is(str1, str3)); // false

在这个例子中,str1str2 是直接量,它们的引用地址相同,因此严格相等运算符和 Object.is() 方法都会返回 true。而 str3 是通过构造函数 String 创建的字符串对象,与直接量的引用地址不同,因此比较结果为 false

总结

浅拷贝出来的对象和旧对象的引用地址是不同的。在浅拷贝过程中,会创建一个新的对象,该对象包含了源对象的所有可枚举属性的副本。因此,尽管浅拷贝后的对象可能与源对象具有相同的属性值,但它们是两个不同的对象,存储在内存中的不同位置,拥有不同的引用地址。

在这里插入图片描述

引用别人的文章:

http://t.csdnimg.cn/zSoTn


let arrayA = [1, '这是一个字符串', undefined, null, { obj: '这是一个obj' }];
console.log('原始的arrayA', arrayA)//原始的arrayA [1, 2, 3, 4, 5, 6, 7]
let arrayB = Array.from(arrayA)//浅拷贝(注意,浅拷贝只会拷贝一层)
let arrayC = arrayA//应用arrayA的堆地址arrayA[0] = 99
arrayA[1] = "修改一下这个字符串"
arrayA[2] = "修改一下这个undefind"
arrayA[3] = "修改一下这个null"
arrayA[4].obj = "修改一下这个obj"console.log('arrayA', arrayA)//[99, '修改一下这个字符串', 修改一下这个undefind, 修改一下这个null, { obj: '修改一下这个obj' }];
//arrayB是由Array.form浅拷贝来的,
console.log('arrayB', arrayB)//[1, '这是一个字符串', undefined, null, { obj: '修改一下这个obj' }]
//arrayC地址应用(arrayC是指向arrayA这个数组对象的堆内存的内存地址),所以arrayA改变后arrayC也会改变,因为它两指向的是同一个内存地址;
console.log('arrayC', arrayC)//[99, '修改一下这个字符串', 修改一下这个undefind, 修改一下这个null, { obj: '修改一下这个obj' }];

在这里插入图片描述

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

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

相关文章

2、选择什么样的机器人本体

如果说世界是物质的,那么应该先制造出机器人的本体,再让她产生灵魂。如果是精神的呢,世界是无中生有的呢,那就先在仿真中研究算法吧。 而我比较崇尚初中哲学的一句话,世界是物质的,物质是运动的&am…

淘宝电商数据API接口

淘宝电商数据API接口:解锁商业智能,助您决策无忧 点击获取数据 在数字化浪潮席卷全球的今天,电商行业早已不再满足于传统的经营模式。随着大数据、人工智能等技术的飞速发展,电商数据成为了企业决策的重要依据。淘宝电商数据API…

【Vue】自定义事件实现组件之间的通信(案例讲解)

一、前言 这是部分哔哩哔哩上跟着一个博主【遇见狂神说】学习的,当然自己也是才开始学习的vue,在学到这个Vue的自定义事件的时候,虽然知识点很绕,但是在理解后又觉得很意思,觉得Vue真的很强大。这里博主将自己学习到的…

浅谈——“总线系统”

系统总线:三总线系统 数据总线: CPU与内存或其他器件之间的数据传送的通道,决定了CPU和外界的数据传送速度。 每条传输线一次只能传输1位二进制数据。 例如:8根数据线一次可传送一个8位二进制数据(即一个字节&#xff…

Python 二叉树的基本操作实现

在Python中实现二叉树的基本操作通常涉及以下步骤: 定义二叉树节点:创建一个类来表示二叉树的节点,通常包含一个数据属性和指向左右子节点的指针。 创建二叉树:允许用户输入数据来构建二叉树。 遍历二叉树:实现前序、…

解释PostgreSQL中的MVCC(多版本并发控制)机制是如何工作的?

文章目录 MVCC的工作原理1. 数据行版本化2. 事务ID和可见性3. 清理旧版本 解决方案:MVCC的优势1. 高并发性2. 避免锁竞争3. 一致性视图 示例代码 PostgreSQL中的MVCC(多版本并发控制)机制是一种在数据库管理系统中实现事务隔离级别的方法&…

vue中的mixin(局部混入、全局混入)

一、mixin是什么 Mixin是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类;Mixin类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂 Vue中的mixin…

如何远程访问路由器?

远程访问路由器是一种方便的技术,使用户可以远程操作和配置他们的网络设备。无论用户身在何处,只要有互联网连接,就可以远程访问家庭或办公室的路由器。在这篇文章中,我将介绍远程访问路由器的优势以及一种名为【天联】的组网产品…

数据结构之双链表的相关知识点及应用

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构 目录 双链表的实现 初始化双链表 在双链表中尾插数据 在双链表中尾删数据 在双链表中头插数据 在双链表中头删数据 在双…

低代码技术与仓储管理的新纪元:革命性的供应链变革

引言 在当今数字化时代,企业对于创新和效率的追求越发迫切。在这样的背景下,低代码技术应运而生,成为企业数字化转型的重要工具之一。低代码技术的崛起为企业提供了一种快速、灵活、成本效益高的开发方式,大大缩短了软件开发周期…

POJO,Entity,model,domain,view,DTO,VO,Param这些分别都是什么含义?怎样理解?

目录 1. 前言 2. POJO的含义 3. entity(实体) 4. model(模型) 5. domain(域) 6. view(视图) 7. DTO(数据传输对象) 8. VO(真正视图层) 9. Param(参数) 10. 总结 1. 前言 在日常开发的过程中,如果我们接手一个新的项目之后,通常会有各种各样的…

浅谈免杀下的持久化

文章目录 前记注册表计划任务COM劫持后记reference 前记 实战中持久化的手段常用的就是加服务、添改注册表、加计划任务、劫持等,这里探索c/c下的维权免杀 注册表 用户级 \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run \HKEY_CURRENT_USER…

代码随想录算法训练营DAY36|C++贪心算法Part.5|435.无重叠区间、763.划分字母区间、56. 合并区间

文章目录 435.无重叠区间按右边界排序CPP代码 按左边界排序如何判断相邻区间是否重叠如何判断一下一个区间与当前相邻区间是否重叠总结CPP代码 763.划分字母区间思路伪代码实现CPP代码 56. 合并区间思路CPP代码 435.无重叠区间 力扣题目链接 文章链接:435.无重叠区间…

Python 0基础_变现_38岁_day 15(匿名函数)

匿名函数: 不用定义函数名,无需使用def关键字,使用lambda将函数写成一行;#使用匿名函数定义一个两个数字相加的函数add lambda x,y : xy #使用变量接收匿名函数的内容,且变量名作为调用函数的变量名&#xff1…

EasyRecovery数据恢复软件2025破解版安装包下载

EasyRecovery数据恢复软件的主要功能及使用教程。coco玛奇朵可以提供一个概要和简化的教程,以便你了解其基本内容和操作步骤。 EasyRecovery绿色破解下载网盘链接: https://pan.baidu.com/s/1_6NmcOh_Jmc-DGc4TJD-Mg?pwddq4w 提取码: dq4w 复制这段内容后打开百度…

强固型工业电脑在称重系统+叉车电脑,称重量体扫码一体机,物流分拣线工作站行业应用

称重系统叉车电脑行业应用 背景介绍 在叉车上安装称重传感器,通过对举升压力的自动检测,将压力信号转换为电流或电压信号,经过A/D转换,使模拟信号变为数字信号,经微处理器进行数据处理后通过蓝牙、串口或者USB接口将称…

深度优先搜索与广度优先搜索,你知道它们的区别吗?

什么是深度优先搜索? 深度优先搜索(DFS,Depth-First Search)是算法中的一种重要的搜索策略。它的核心思想是“深入探索,直至无路可走,然后再回溯”。这种策略在许多问题中都有着广泛的应用,例如…

dial tcp 192.168.0.190:443: connect: connection refused

1、场景 用nerdctl登录镜像仓库192.168.0.190(Harbor),报错 ERRO[0006] failed to call tryLoginWithRegHost error"failed to call rh.Client.Do: Get \"https://192.168.0.190/v2/\": dial tcp 192.168.0.190:…

【数据结构】图(Graph)

文章目录 概念图的存储方式邻接矩阵邻接矩阵表示法邻接矩阵表示法的特点 邻接表邻接表表示法邻接表表示法的特点邻接表表示法的定义与实现查找插入删除其它构造函数析构函数创建图输出图 图的遍历深度优先遍历(DFS)广度优先遍历 图的连接分量和生成树生成…

Ubuntu20.04安装 nginx1.23.1

1、下载 wget http://nginx.org/download/nginx-1.23.1.tar.gz 2、 安装相关依赖包 sudo apt-get install libpcre3 libpcre3-dev sudo apt-get install zlib1g zlib1g-dev sudo sudo apt-get install openssl sudo sudo apt-get install libssl-dev 3、 解压安装 tar -zx…