对浅拷贝的理解

news2024/11/16 1:40:05

问题背景

我之前一直以为浅拷贝出来的新对象和旧对象的引用地址是相同的,但是通过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); // false
    console.log(obj1 === obj3); // true
    console.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)); // true
    console.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.coloradmin.cn/o/1622020.html

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

相关文章

Kafka源码分析(四) - Server端-请求处理框架

系列文章目录 Kafka源码分析-目录 一. 总体结构 先给一张概览图: 服务端请求处理过程涉及到两个模块:kafka.network和kafka.server。 1.1 kafka.network 该包是kafka底层模块,提供了服务端NIO通信能力基础。 有4个核心类:…

spring的bean创建流程源码解析

文章目录 IOC 和 DIBeanFactoryApplicationContext实现的接口1、BeanFactory接口2、MessageSource 国际化接口3、ResourcePatternResolver,资源解析接口4、EnvironmentCapable接口,用于获取环境变量,配置信息5、ApplicationEventPublisher 事…

GAN详解,公式推导解读,详细到每一步的理论推导

在看这一篇文章之前,希望熟悉掌握熵的知识,可看我写的跟熵相关的一篇博客https://blog.csdn.net/m0_59156726/article/details/138128622 1. GAN 原始论文:https://arxiv.org/pdf/1406.2661.pdf 放一张GAN的结构,如下&#xff1…

索引超详细解析

目录 索引概述 无索引时: 索引: 索引结构 介绍: 二叉树: B-Tree(多路平衡查找树): 经典BTree MySQL中B树 Hash索引 hash索引的特点: 存储引擎支持: 为什么InnoDB存储选择使用BTree…

升级 jQuery:努力打造健康的 Web 生态

jQuery 对 Web 的影响始终是显而易见的。当 jQuery 在 2006 年首次推出时,几乎立即成为 Web 开发人员的基本工具。它简化了 JavaScript 编程,使操作 HTML 文档、处理事件、执行动画等变得更加容易。从那时起,它在 Web 标准和浏览器功能的演变…

深度学习基础:循环神经网络中的Dropout

深度学习基础:循环神经网络中的Dropout 在深度学习中,过拟合是一个常见的问题,特别是在循环神经网络(RNN)等复杂模型中。为了应对过拟合问题,研究者们提出了许多方法,其中一种被广泛应用的方法…

CSS渐变色理论与分类、文字渐变色方案、炸裂渐变色方案以及主流专业渐变色工具网站推荐

渐变色彩可以增加视觉层次感和动态效果,使网页界面更加生动有趣,吸引用户注意力。另外,相较于静态背景图片,CSS渐变无需额外的HTTP请求,减轻服务器负载,加快页面加载速度;同时CSS渐变能够根据容…

应用软件运维服务方案(word原件)

信息化项目运维服务方案(投标,实施运维,交付) 1.项目整体介绍 2.服务简述 3.资源提供 软件全过程性,标准型,规范性文档(全套资料包)获取:本文末个人名片直接获取&…

WPS二次开发系列:WPS SDK打开在线文档

作者持续关注WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 目录 需求场景 效果展示 3、实现步骤 3.1 步骤一、申…

spring boot3单模块项目工程搭建-下(个人开发模板)

⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 🌊山高路远,行路漫漫,终有归途 目录 写在前面 上文衔接 常用依赖介绍以及整合 web组件 测试组件 样板代码生成 数据库连接器 常用工具包 面向切面编…

《QT实用小工具·三十九》仿 Windows10 画图3D 的颜色选择器, 但更加强大

1、概述 源码放在文章末尾 该项目实现了仿 Windows10 画图3D 的颜色选择器,功能更加丰富更加强大。 项目部分代码如下所示: import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import QtGraphicalEffects 1.15Item {id…

【踩坑】libtorch load 报错 No such file or directory

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,请不吝给个[点赞、收藏、关注]哦~ 目录 报错背景 报错原因 解决方法 方法一:把你的编译配置转为release版本 方法二:安装debug版本的libtorch 报错背景…

算法学习001-圆桌问题 中小学算法思维学习 信奥算法解析 c++实现

目录 算法学习001-圆桌问题 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 算法学习001-圆桌问题 一、题目要求 1、编程实现 圆桌边围坐着2n个人,其中n个人是好人&#xff0c…

Redis 安装及配置教程(Windows)【安装】

文章目录 一、简介一、 下载1. GitHub 下载2. 其它渠道 二、 安装1. ZIP2. MSI 软件 / 环境安装及配置目录 一、简介 Redis 官网地址:https://redis.io/   Redis 源码地址:https://github.com/redis/redis   Redis 官网安装地址(无Windo…

基于SSM的物业管理系统(含源码+sql+视频导入教程+文档+PPT)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的物业管理系统2拥有三种角色 管理员:用户管理、物业管理、房产信息管理、小区概况管理、开发商管理、收费标准管理、物业公司管理等 物业:住户管理、收费…

vector的使用(部分接口)

1.vector的使用 1.1vector的定义 (constructor)构造函数声明接口说明vector()无参构造vector (const vector& x)拷贝构造 1.2vector iterator 的使用 iterator的使用接口说明begin end获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位…

【数据结构】单链表的特点

🎈个人主页:豌豆射手^ 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:数据结构 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进…

UML——类图详解

目录 1. 前言 2. 类图概述 3. 类图表示法 3.1 类的表示方式 3.2 类与类之间关系的表示方式 (1)继承(泛化)关系 (2)实现关系 (3)依赖关系 (4)一般关联关系 (5)聚合关系 (6)组合关系 1. 前言 UML全称(Unified Modeling Language),译为统一建模语言&#x…

Android自定义ListView单击事件失效的解决方法

因为自带的listView不能满足项目需求,通过实现自己的Adapter去继承ArrayAdapter 来实现自定义ListView的Item项目。 出现点击ListView的每一项都不会执行setOnItemClickListener 里面的onItemClick 方法。 原因是item里面存在一些子控件,默认点击获取的…

使用 PhpMyAdmin 安装 LAMP 服务器

使用 PhpMyAdmin 安装 LAMP 服务器非常简单。按照下面所示的步骤,我们将拥有一个完全可运行的 LAMP 服务器(Linux、Apache、MySQL/MariaDB 和 PHP)。 什么是 LAMP 服务器? LAMP 代表 Linux、Apache、MySQL 和 PHP。它们共同提供…