JavaScript如何实现数据的深拷贝、浅拷贝?

原文合集地址如下,有需要的朋友可以关注

本文地址

什么是深浅拷贝

说到深浅拷贝就得提起JavaScript中的数据类型之前的文章中有介绍过,这里就不再细说了。
浅拷贝:对基本数据类型进行值复制,对引用数据类型复制引用地址。浅拷贝会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果拷贝的是像对象这样的引用对象,那么浅拷贝会复制引用指向堆内存地址,因此源对象和拷贝对象会共享属性。
深拷贝:对基本数据类型进行值复制,对引用数据类型递归复制。深拷贝会另外创造一个一摸一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
区别举例:

// 原始对象
let obj = {a: 1,b: {c: 2}
}// 浅拷贝
let shallowCopy = Object.assign({}, obj) // 深拷贝
let deepCopy = JSON.parse(JSON.stringify(obj))obj.b.c = 3
console.log(shallowCopy.b.c) // 3
console.log(deepCopy.b.c) // 2

如何实现

在 JavaScript 中,拷贝操作用于复制对象或数组的值,以便在不影响原始对象的情况下进行操作。拷贝分为深拷贝和浅拷贝两种类型。

浅拷贝(Shallow Copy):

常见的浅拷贝方式包括:

  1. 扩展操作符(Spread Operator):
    使用 ... 操作符进行浅拷贝。

    const originalArray = [1, 2, 3];
    const shallowCopy = [...originalArray];
    
  2. Object.assign() 方法:
    使用 Object.assign() 方法将属性从一个或多个源对象复制到目标对象。

    const originalObj = { a: 1, b: 2 };
    const shallowCopy = Object.assign({}, originalObj);
    

深拷贝(Deep Copy):

深拷贝创建了一个新对象,并递归地复制原始对象的所有属性及其嵌套属性,确保每个引用类型都是独立的新对象,不会与原始对象共享。

常见的深拷贝方式包括:

  1. 使用递归:
    递归遍历对象的所有属性,并在遇到引用类型时继续递归。

    function deepCopy(obj) {if (typeof obj !== 'object' || obj === null) {return obj;}const copy = Array.isArray(obj) ? [] : {};for (const key in obj) {if (obj.hasOwnProperty(key)) {copy[key] = deepCopy(obj[key]);}}return copy;
    }
    
  2. JSON 序列化与反序列化:
    通过先将对象转换为 JSON 字符串,然后再将其解析回对象,实现深拷贝。但这种方法有一些限制,不能复制函数、正则表达式等。

    const originalObj = { a: 1, nested: { b: 2 } };
    const deepCopy = JSON.parse(JSON.stringify(originalObj));
    

需要注意什么问题

在使用拷贝操作时,有一些重要的注意事项需要考虑,特别是在处理复杂的对象和数据结构时。以下是需要注意的几点:

  1. 引用类型:
    拷贝操作通常在处理引用类型(如对象和数组)时更为复杂。浅拷贝可能只复制引用,而深拷贝可能导致性能问题。理解被拷贝对象中的引用关系是很重要的。

  2. 循环引用:
    如果要拷贝的对象中存在循环引用(即对象 A 引用了对象 B,而对象 B 又引用了对象 A),那么简单的拷贝操作可能会导致无限递归或栈溢出。在实现深拷贝时,需要考虑如何处理循环引用。

  3. 性能考虑:
    深拷贝可能在处理大型对象或嵌套深度很深的结构时变得很慢,因为它需要递归地复制每个属性。在这些情况下,可能需要选择性地使用浅拷贝或者其他优化方法。

  4. 不可拷贝属性:
    一些对象的属性是不可枚举或不可拷贝的(例如原型链上的属性)。在拷贝操作中,这些属性可能被忽略。

  5. 函数和特殊对象:
    函数和一些特殊的对象(如正则表达式、Date 对象等)可能需要特殊的处理,特别是在使用深拷贝时。这些对象可能无法通过 JSON 序列化来实现深拷贝。

  6. 性能和内存开销:
    拷贝操作可能导致性能问题和额外的内存开销,特别是在处理大数据结构时。在做出选择时,需要权衡性能和内存使用。

可以考虑使用成熟的第三方库,如 lodash 的 .clone、.cloneDeep 方法,它们在处理拷贝时已经考虑了很多复杂情况。

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

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

相关文章

队列(Queue):先进先出的数据结构队列

栈与队列https://blog.csdn.net/qq_45467165/article/details/127958960?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127958960%22%2C%22source%22%3A%22qq_45467165%22%7D 队列(Queue)是一种常见的线…

Apache Shiro是什么

特点 Apache Shiro是一个强大且易用的Java安全框架,用于身份验证、授权、会话管理和加密。它的设计目标是简化应用程序的安全性实现,使开发人员能够更轻松地处理各种安全性问题,从而提高应用程序的安全性和可维护性。下面是一些Apache Shiro的关键特点和概念: 特点和概念…

【芯片设计封装与测试】芯片测试目的、方法、分类及案例

目录 1.芯片测试概述(目的、方法) 1.1.测试在芯片产业价值链上的位置 2.测试如何体现在设计的过程中 2.1.半导体测试定义与基本工作机制 2.2.半导体测试环节分类及对应设备 2.3.设计验证 3.测试的各种类型 3.1.抽样测试和生产全测 3.2.测试相关…

controller层如何接收带参数的查询

在控制器(Controller)层接收带参数的查询可以通过多种方式实现。以下是几种常见的方法: 使用 URL 路径参数:将参数作为 URL 的一部分,例如 /users/{userId}。在 Spring MVC 中,您可以使用 PathVariable 注解…

Mysql知识梳理

Mysql知识梳理 索引索引分类索引未命中的原因性能调优命令Explain回表 mysql性能优化事务四大特性事务隔离级别设置事务隔离级别 存储引擎聚簇索引和非聚簇索引聚簇索引非聚簇索引 最左前缀结合原则全文索引 索引 索引分类 mysql有普通索引、空间索引、主键索引、唯一索引、组…

高忆管理:股市交易时间和规则?

股市是指股票买卖商场,出资者买卖股票来获取出资回报。买卖时刻和规矩是股票商场的核心,它约束了股票价格的改变和买卖者的行为。那么,股市的买卖时刻和规矩是什么?咱们应该怎么了解和运用它们来出资? 一、股市买卖时刻…

集成放大器 电路 分析 设计过程中的概念和要点

集成运放的三大特性:虚短、虚断、 和 虚地把这几个特性理解明白了, 后面的电路分析就很容易上手。 虚短:UPUN,两输入端电压相等。虚断:IPIN0,两输入端的输入电流为0。虚地:UPUN0&#xff0c…

Python Scrapy网络爬虫框架从入门到实战

Python Scrapy是一个强大的网络爬虫框架,它提供了丰富的功能和灵活的扩展性,使得爬取网页数据变得简单高效。本文将介绍Scrapy框架的基本概念、用法和实际案例,帮助你快速上手和应用Scrapy进行数据抓取。 Scrapy是一个基于Python的开源网络爬…

软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章三

软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章三 一、论Web Service 技术的应用与发展趋势1.论文题目2.写作要点和写作素材二、论系统的可靠性1.论文题目2.写作要点和写作素材三、论软件可靠性设计与应用1.论文题目2.写作要点和写作素材四、论软件…

17.1.2 【Linux】systemd使用的unit分类

systemd 有什么好处? 平行处理所有服务,加速开机流程: 旧的 init 启动脚本是“一项一项任务依序启动”的模式,因此不相依的服务也是得要一个一个的等待。但目前我们的硬件主机系统与操作系统几乎都支持多核心架构了,s…

【路由器】小米 WR30U 解锁并刷机

文章目录 解锁 ssh环境准备解锁过程 刷入 mt798x uboot简介刷入流程 刷入 ImmortalWrt简介刷入流程 刷为原厂固件参考资料 本文主要记录个人对小米 WR30U 路由器的解锁和刷机过程,整体步骤与 一般安装流程 类似,但是由于 WR30U 的解锁 ssh 和刷机的过程中…

【AWS】安装配置适用于 Eclipse 的 AWS 工具包

目录 0.环境 1.步骤 1)安装Eclipse 2)安装AWS工具包 ① 在这个路径下点开安装软件的界面 ② 点击【Add】打开添加窗口 ③ 输入aws的工具包地址 ④ 勾选需要的工具,点击【Next】 ⑤ 将要安装的工具,点击【Next】 ⑥ 选择接受…

华为云CodeArts Snap 智能编程助手PyCharm实验手册. 插件安装与使用指南

作为一款自主创新的AI代码辅助编程工具,华为云智能编程助手CodeArts Snap目标打造现代化开发新范式。通过将自然语言转化为规范可阅读、无开源漏洞的安全编程语言,提升开发者编程效率,助力企业快速响应市场需求。华为云CodeArts Snap现进入邀…

运算放大器发展史

在内部集成了一个补偿电容 MPS公司OP07推出后,大受欢迎。各家厂商都推出了自己的 这4款都是可以替换的

Delphi 中接口实现:Implementing Interfaces

目录 一、类声明(Class Declarations) 二、方法解决说明(Method Resolution Clause) 三、更改继承实现(Changing Inherited Implementations) 四、通过委托实现接口(Implementing Interface…

【锐捷】OSPF 多区域配置

【实验名称】 配置 OSPF 多区域。 【实验目的】 配置 OSPF 多区域,理解 OSPF 层次型网络的特点。 【背景描述】 本实验拓扑图中有 3 台路由器,路由器在区域 0 和区域 1 中,路由器 B 在区域 0 和区域 30, 路由器 C 在区域 30。 【需…

Rocket消息存储

一、存储介质 ● 关系型数据库DB Apache下开源的另外一款MQ—ActiveMQ (默认采用的KahaDB做消息存储)可选用JDBC的方式来做消息持久化,通过简单的xmI配置信息即可实现JDBC消息存储。由于,普通关系型数据库(如Mysql)在单表数据量达到千万级别的情况下&a…

linux安装部署gitlab全教程,包含配置中文

linux安装部署gitlab全教程,包含配置中文 大家好,我是酷酷的韩~ 1.前期准备 安装包下载地址 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 我这里选择的这个gitlab-ce-15.7.3-ce.0.el7.x86_64.rpm 还有一些相关依赖包(地址等审核过我放到…

pdf编辑文字怎么编辑?这几种简单编辑方法看一看

pdf编辑文字怎么编辑?PDF文件是一种普遍的文档格式,但是在编辑时却比较困难。幸运的是,有许多PDF编辑器可以帮助我们轻松地编辑PDF文件。本文将介绍一些简单的PDF编辑方法,跟着我一起来看看吧! 第一种方法:…

docker for window更改到非系统盘的使用记录

1、使用Hyper-v模式的docker安装 2、安装docker for windows后安装目录没办法自己选择,固定在c盘 卸载后通过命令行方式设置软连接方式后重新安装来让其安装到软连接的d盘,解决c盘空间问题 mklink /j "C:\Program Files\Docker" "D:\Pr…