js的深浅拷贝
深浅拷贝是编程中对数据复制的两种不同方式,它们在处理对象和数组等复合数据结构时尤为重要。下面将详细解释这两种拷贝方式。
浅拷贝(Shallow Copy)
浅拷贝创建了原始对象的一个新实例,但这个新实例的属性只是原始对象属性的引用。如果属性是基本数据类型(如数字、字符串、布尔值),那么它们会被复制;如果属性是引用类型(如对象、数组),则新对象的属性只是指向原始对象属性的引用。
特点:
- 创建新对象,但只复制第一层属性。
- 对于嵌套的对象或数组,新对象的属性与原始对象的属性指向相同的内存地址。
- 修改新对象的嵌套属性,会影响原始对象。
例子:
-
使用
Object.assign()
:let original = { a: 1, b: { c: 2 } }; let shallow = Object.assign({}, original); shallow.b.c = 3; // 这会同时改变 original.b.c 的值
-
使用扩展运算符:
let original = [1, 2, { d: 4 }]; let shallow = [...original]; shallow[2].d = 5; // 这会同时改变 original[2].d 的值
-
使用数组的
slice()
方法:let original = [1, 2, 3]; let shallow = original.slice(); shallow.push(4); // 这不会改变 original,因为数组是新的
深拷贝(Deep Copy)
深拷贝创建了原始对象的一个完全独立的副本,包括所有嵌套的对象和数组。修改新对象的任何属性都不会影响原始对象。
特点:
- 创建一个全新的对象,递归复制所有层级的属性。
- 对于嵌套的对象或数组,新对象的每个属性都是原始属性的独立副本。
- 修改新对象的任何属性,原始对象不受影响。
例子:
-
使用递归函数:
function deepCopy(obj) {if (typeof obj !== 'object' || obj === null) return obj;let clone = Array.isArray(obj) ? [] : {};for (let key in obj) {clone[key] = deepCopy(obj[key]);}return clone; } let original = { a: 1, b: { c: 2 } }; let deep = deepCopy(original); deep.b.c = 3; // 这不会改变 original.b.c 的值
-
使用
JSON.stringify()
和JSON.parse()
:let original = { a: 1, b: { c: 2 } }; let deep = JSON.parse(JSON.stringify(original)); deep.b.c = 3; // 这不会改变 original.b.c 的值
特殊情况
- 函数:深拷贝通常不会复制函数,因为
JSON.stringify()
会忽略函数。 - 特殊对象:如
Date
,RegExp
,Map
,Set
等,在JSON.stringify()
中不会被正确处理。 - 循环引用:
JSON.stringify()
无法处理循环引用的对象,会导致错误。
例子 1:函数
let original = { name: 'Alice', greet: function() { console.log('Hello, ' + this.name); } };
let deepCopy = JSON.parse(JSON.stringify(original));deepCopy.greet(); // TypeError: deepCopy.greet is not a function
例子 2:循环引用
let original = {};
original.self = original;let deepCopy = JSON.parse(JSON.stringify(original));
console.log(deepCopy.self === original.self); // 输出: false
例子 3:特殊值
let original = { name: 'Alice', value: undefined };
let deepCopy = JSON.parse(JSON.stringify(original));console.log(deepCopy.value); // 输出: undefined
例子 4:正则表达式
let original = { name: 'Alice', pattern: /abc/ };
let deepCopy = JSON.parse(JSON.stringify(original));console.log(original.pattern.test('abc')); // 输出: true
console.log(deepCopy.pattern.test('abc')); // 输出: false
例子 5:Map 和 Set
let original = { name: 'Alice', map: new Map([['key', 'value']]), set: new Set([1, 2, 3]) };
let deepCopy = JSON.parse(JSON.stringify(original));console.log(original.map.get('key')); // 输出: value
console.log(deepCopy.map.get('key')); // 输出: undefined
区别
通过这些例子,你可以看到深浅拷贝在不同情况下的表现,以及它们在实际应用中的适用性和局限性。
深浅拷贝的区别主要体现在它们复制数据结构的方式和结果上。以下是深浅拷贝的主要区别:
-
复制深度:
- 浅拷贝:只复制了对象的第一层属性。如果对象的属性是引用类型(如数组或对象),浅拷贝只会复制引用,而不是实际的对象或数组。
- 深拷贝:递归地复制了对象的所有层级,包括嵌套的对象或数组。每个属性都是原始属性的独立副本,不共享内存地址。
-
内存地址:
- 浅拷贝:新对象和原始对象共享一些引用类型的属性的内存地址。
- 深拷贝:新对象和原始对象的所有属性都有独立的内存地址,互不影响。
-
独立性:
- 浅拷贝:新对象和原始对象不是完全独立的,修改新对象中引用类型的属性可能会影响原始对象。
- 深拷贝:新对象和原始对象是完全独立的,对新对象的任何修改都不会影响到原始对象。
-
性能:
- 浅拷贝:通常比深拷贝更快,因为它只复制了对象的第一层属性。
- 深拷贝:可能更慢,因为它需要递归地复制所有层级的属性。
-
适用场景:
- 浅拷贝:适用于只需要复制对象的第一层属性,或者对象中不包含复杂的嵌套引用。
- 深拷贝:适用于需要完全独立的副本,特别是当对象包含多层嵌套的引用类型时。
-
实现方式:
- 浅拷贝:可以通过
Object.assign()
, 扩展运算符(...
),Array.prototype.slice()
等方法实现。 - 深拷贝:可以通过递归函数实现,或者使用
JSON.stringify()
和JSON.parse()
(但有局限性)。
- 浅拷贝:可以通过
-
局限性:
- 浅拷贝:无法处理循环引用,且不会复制函数和特殊对象(如
Date
,RegExp
,Map
,Set
等)。 - 深拷贝:使用
JSON.stringify()
和JSON.parse()
时,无法处理函数、特殊对象和循环引用。
- 浅拷贝:无法处理循环引用,且不会复制函数和特殊对象(如
-
副作用:
- 浅拷贝:由于共享引用,修改新对象可能会产生意外的副作用,影响到原始对象。
- 深拷贝:由于完全独立,修改新对象不会产生副作用。
理解这些区别对于在实际编程中选择合适的数据复制策略非常重要。选择不当可能会导致数据不一致或程序错误。
结论
深浅拷贝的选择取决于你需要复制的数据结构和预期的行为。如果你需要一个完全独立的副本,深拷贝是必要的。如果你只是需要复制第一层的属性,并且不关心嵌套对象的独立性,浅拷贝就足够了。然而,深拷贝也有其局限性,比如无法处理函数和特殊对象,以及循环引用的问题。在实际开发中,了解这些差异对于避免潜在的错误至关重要。
相关文章:

js的深浅拷贝
深浅拷贝是编程中对数据复制的两种不同方式,它们在处理对象和数组等复合数据结构时尤为重要。下面将详细解释这两种拷贝方式。 浅拷贝(Shallow Copy) 浅拷贝创建了原始对象的一个新实例,但这个新实例的属性只是原始对象属性的引…...

实验八: 彩色图像处理
目录 一、实验目的 二、实验原理 1. 常见彩色图像格式 2. 伪彩色图像 3. 彩色图像滤波 三、实验内容 四、源程序和结果 (1) 主程序(matlab (2) 函数FalseRgbTransf (3) 函数hsi2rgb (4) 函数rgb2hsi (5) 函数GrayscaleFilter (6) 函数RgbFilter 五、结果分析 1. …...

Python酷库之旅-第三方库Pandas(048)
目录 一、用法精讲 171、pandas.Series.nlargest方法 171-1、语法 171-2、参数 171-3、功能 171-4、返回值 171-5、说明 171-6、用法 171-6-1、数据准备 171-6-2、代码示例 171-6-3、结果输出 172、pandas.Series.nsmallest方法 172-1、语法 172-2、参数 172-3、…...

springboot爱宠屋宠物商店管理系统-计算机毕业设计源码52726
目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…...

自训练和增量训练word2vec模型
1、自己准备训练语料文件 根据自己的业务场景准备训练数据,比如用户在商城上的同购行为序列或同浏览行为序列。 我们希望通过自己训练业务相关的语料word2vec模型来获得词嵌入、词相关性查询等。 1.1 准备语料库文件 # 示例:准备自己的一个大规模的语…...

华三路由器开启web访问
配置路由器: # 配置Web用户名为admin,认证密码为admin,服务类型为http,用户角色为network-admin。 [Sysname] local-user admin [Sysname-luser-manage-admin] service-type http [Sysname-luser-manage-admin] authorization…...

C++软件开发值得推荐的十大高效软件分析工具
目录 1、概述 2、高效软件工具介绍 2.1、窗口查看工具SPY 2.2、Dependency Walker 2.3、剪切板查看工具Clipbrd 2.4、GDI对象查看工具GDIView 2.5、Process Explorer 2.6、Prcoess Monitor 2.7、API Monitor 2.8、调试器Windbg 2.9、反汇编工具IDA 2.10、抓包工具…...

vue2老项目中node-sass更换dart-sass
更换原因:node-sass经常会出现node版本问题,就很麻烦 卸载项目中的node-sass sass-loader npm uninstall sass-loader sass 安装dart-sas sass-loader 推荐安装sass1.26.2 sass-loader7.3.1 npm install sass-loader7.3.1 sass1.26.2 从新配置vue.…...

源/目的检查开启导致虚拟IP背后的LVS无法正常访问
情况描述 近期发现48网段主机无法访问8.83这个VIP(虚拟IP),环境是 8.83 绑定了两个LVS实例,然后LVS实例转发到后端的nginx 静态资源;整个流程是,客户端发起对VIP的请求,LVS将请求转发到后端实例…...

类和对象(四)
构造函数中的初始化列表 之前在实现构造函数时,主要是在函数体内进行赋值,而构造函数还有另一种初始化方式,通过初始化列表进行初始化。 初始化列表的使⽤⽅式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,…...

<PLC><HMI><汇川>在汇川HMI画面中,如何为UI设置全局样式?
前言 汇川的HMI软件是使用了Qt来编写的,因此在汇川的HMI程序编写过程,是支持使用qt的样式来自定义部件样式的,即qss格式。 概述 汇川的软件本身提供三个系统的style样式,我们可以直接使用,但是,如果系统提供的样式不符合你的需求,那么你可以对其进行修改,或者自己新建…...

在Git项目中添加并应用“.gitignore”文件
在Git项目中添加并应用.gitignore文件 创建或修改.gitignore文件: 在项目的根目录下创建一个名为.gitignore的文件。如果已经有此文件,可以直接修改。 在文件中添加您希望Git忽略的文件和目录。例如: # 忽略所有的log文件 *.log# 忽略所有的…...

LeetCode Hot100 搜索二维矩阵
给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。…...

iOS中的KVO(Key-Value Observing)详解
iOS中的KVO(Key-Value Observing)详解 一、KVO概述 KVO(Key-Value Observing),即键值观察/监听,是苹果提供的一套事件通知机制。它允许一个对象(观察者)观察/监听另一个对象&#…...

算法 —— 暴力枚举
目录 循环枚举 P2241 统计方形(数据加强版) P2089 烤鸡 P1618 三连击(升级版) 子集枚举 P1036 [NOIP2002 普及组] 选数 P1157 组合的输出 排列枚举 P1706 全排列问题 P1088 [NOIP2004 普及组] 火星人 循环枚举 顾名思…...

构造+有序集合,CF 1023D - Array Restoration
一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1023D - Array Restoration 二、解题报告 1、思路分析 先考虑合法性检查: 对于数字x,其最左位置和最右位置 之间如果存在数字比x小,则非法 由于q次操作,第q…...

Scrapy 爬取旅游景点相关数据(四)
本节内容主要为: (1)创建数据库 (2)创建数据库表 (3)爬取数据进MYSQL库 1 新建数据库 使用MYSQL数据库存储数据,创建一个新的数据库 create database scrapy_demo;2 新建数据表 CR…...

Vue常用指令及其生命周期
作者:CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 目录 1.常用指令 1.1 v-bind 1.2 v-model 注意事项 1.3 v-on 注意事项 1.4 v-if / v-else-if / v-else 1.5 v-show 1.6 v-for 无索引 有索引 生命周期 定义 流程 1.常用指令 Vue当中的指令…...

简化数据流:Apache SeaTunnel实现多表同步的高效指南
Apache SeaTunnel除了单表之间的数据同步之外,也支持单表同步到多表,多表同步到单表,以及多表同步到多表,下面简单举例说明如何实现这些功能。 单表 to 单表 一个source,一个sink。 从mysql同步到mysql,…...

均匀圆形阵列原理及MATLAB仿真
均匀圆形阵列原理及MATLAB仿真 目录 前言 一、均匀圆阵原理 二、圆心不存在阵元方向图仿真 三、圆心存在阵元方向图仿真 四、MATLAB仿真代码 总结 前言 本文详细推导了均匀圆形阵列的方向图函数,对圆心不放置阵元和圆心放置阵元的均匀圆形阵列方向图都进行了仿…...

vue2使用univerjs
1、univerjs Univer 提供了一个全面的企业级文档与数据协同的解决方案,支持电子表格、文本文档和演示幻灯片三大核心文档类型。通过灵活的 API 和插件机制,开发者可以在 Univer 的基础上进行个性化功能的定制和扩展,以适应不同用户在不同场景…...

VUE3 el-table-column header新增必填*
1.在需要加必填星号的el-table-column上添加render-header属性 <el-table-column :label"getName(产品代码)" :render-header"addRedStart" prop"MODELCODE" min-width“4.5%”> <template v-slot"scope"> <el-input …...

条件概率和贝叶斯公式
...

Kali中docker与docker-compose的配置
权限升级 sudo su 升级为root用户 更新软件 apt-get update安装HTTPS协议和CA证书 apt-get install -y apt-transport-https ca-certificates下载docker apt下载docker apt install docker.io 验证docker安装是否成功 查版本 docker -v 启动docker systemctl start …...

C++ | Leetcode C++题解之第283题移动零
题目: 题解: class Solution { public:void moveZeroes(vector<int>& nums) {int n nums.size(), left 0, right 0;while (right < n) {if (nums[right]) {swap(nums[left], nums[right]);left;}right;}} };...

Exponential Moving Average (EMA) in Stable Diffusion
1.Moving Average in Stable Diffusion (SMA&EMA) 1.Moving average 2.移动平均值 3.How We Trained Stable Diffusion for Less than $50k (Part 3) Moving Average 在统计学中,移动平均是通过创建整个数据集中不同选择的一系列平均值来分析数据点的计算。 …...

017、Vue动态tag标签
文章目录 1、先看效果2、代码 1、先看效果 2、代码 <template><div class "tags"><el-tag size"medium"closable v-for"item,index in tags":key"item.path":effect"item.title$route.name?dark:plain"cl…...

RocketMQ 架构概览
Apache RocketMQ 是一个分布式消息中间件和流计算平台,提供低延迟、高性能和可靠的队列服务,并且支持大规模的分布式系统。在详细介绍 RocketMQ 的整体架构之前,先了解其设计目标和核心特性是很重要的。RocketMQ 主要用于处理大规模的消息&am…...

优化医疗数据管理:Kettle ETL 数据采集方案详解
在现代医疗保健领域,数据的准确性、完整性和及时性对于提高医疗服务质量和患者护理至关重要。为了有效管理和利用医疗数据,Kettle ETL(Extract, Transform, Load)数据采集方案成为了许多医疗机构的首选工具之一。本文将深入探讨Ke…...

spring-from表单
在spring boot当中,from表单怎样开发(name=value) 先列出接口所需信息(抓包得到请求信息),将这些必要信息以注解的方式表达出来 步骤: 梳理前置条件(请求地址,请求header,请求方法,请求数据,响应结果)编辑一个普通类,在类上标记注解@Controller: 标记在类上,让类…...