JavaScript中的浅拷贝与深拷贝
前言
JavaScript中的浅拷贝和深拷贝是非常重要的概念,它们在处理对象和数组时具有不同的作用。在编程中,经常需要复制数据以便进行各种操作,但必须注意拷贝的方式,以确保得到预期的结果。
浅拷贝是创建一个新对象或数组,并将原始对象或数组的引用复制给它。这意味着新对象和原始对象将共享相同的内存地址,修改其中一个对象的属性或元素也会影响另一个对象。相反,深拷贝是创建一个完全独立的对象或数组,新的拷贝将具有与原始对象或数组相同的值,但是它们在内存中是彼此独立的,相互之间的修改不会互相影响。
本文小编将为大家介绍JavaScript中实现浅拷贝和深拷贝的不同方法,并提供示例代码作为辅助。
基本拷贝
下面是一个基本的拷贝,新的拷贝对象会专门开辟一块内存空间——二者的类型、值都是独立可变的,换句话说,他们是通过将值传递给新对象完成拷贝的。
//原始值拷贝
let x = 400
let y = x
x = "This string"
console.log(y) //400
console.log(x) //This string
当y被创建时,它的值被赋予了x的值(因为这是在运行时,x被重新赋值之前)。这里重要的一点是,读者可以通过创建另一个变量并将其分配给要复制的变量来快速将原始数据类型的精确值复制到单独的内存空间中。请注意它是如何实例化的——const 不允许再进行更改。

(内存分配和原始赋值的视觉进展)
//小编可以走的更深一些,在上面的代码中,再将x设置为原始数据类型;
//当然了,小编都知道它们是在不同的内存空间,只不过值是相同的
let x = 400
let y = x
x = "This string"
console.log(y) //400
console.log(x) //This string
x = 400
console.log(x) // 400
console.log(y) // 400
浅拷贝
以下是一个展示浅拷贝的示例。在此示例中,拷贝了一个包含文字的浅对象。由于浅拷贝只会复制原始对象的引用而非值本身,所以被拷贝的对象和原始对象将共享相同的内存空间,即它们的值也将相同。需要注意的是,在 JavaScript 中,“浅对象”是指一种非嵌套且非原始的 JavaScript 数据类型。
// 浅对象的浅拷贝
let ShallowObj= {
key1: 1,
key2: 2,
}
let newObj = ShallowObj// 一个简单的重新分配为 newObj 创建共享内存
ShallowObj.key1 = 5
console.log(shallowObj) // {key1: 5, key2: 2}
console.log(newObj) // {key1: 5, key2: 2}
当重新分配ShallowObj中key1的值时,会导致newObj中key1的值也随之发生改变。尽管这两个对象具有不同的变量名称,但它们实际上共享相同的内存空间。因此,如果需要更改shallowObj.key1的值,可以直接修改newObj.key1来获得相同的结果。这在某些情况下非常有用,例如当需要表示一组具有相同属性和值的特定对象时。然而,在运行时,可能需要给这些浅拷贝对象赋予不同的变量名称,以满足应用程序的需求,并作为不同的props传递给其他组件。通过使用不同的变量名称,可以根据不同的目标在应用程序中对它们进行独立操作,以实现所需的功能。
对浅对象进行深拷贝
//使用 Object.assign()
let myRadio = { podcasts: 19,
albums: 378,
playlists: 44
}
let deepCopyMyRadio = Object.assign( {}, myRadio )
deepCopyMyRadio.playlists = 62 // 只改变 deepCopyMyRadio
console.log(deepCopyMyRadio) // => { podcasts: 19,
albums: 378,
playlists: 62
}
console.log(myRadio) // => { podcasts: 19,
albums: 378,
playlists: 44
}
ES6引入了一种新特性称为扩展运算符。扩展运算符用三个连续的点"..."表示,并可以在代码的多个地方使用。通常情况下,扩展运算符会为给定对象的每个顶级属性创建副本,并将它们扩展到新对象中。在特定情况下,可以选择使用浅拷贝或深拷贝来处理嵌套对象。在本例中,展示的是浅对象的深拷贝,因此可以使用Object.assign()方法或以下示例即可。
//用扩展运算符深拷贝
let myRadio = { podcasts: 9,
albums: 38,
playlists: 4
}
let copyMyRadio = { ...myRadio }
myRadio.albums = 88 // 还是只改变myRadio
console.log(myRadio) //=> { podcasts: 9, albums: 88, playlists: 4 }
console.log(copyMyRadio) //=> {podcasts: 9,albums: 38, playlists: 4}
不过这种写法的问题在于,随着项目规模和复杂性的增加,扩展运算符是一个有局限的解决方案。扩展运算符可以处理浅对象的深拷贝(非嵌套),即将一个对象的顶级属性复制到另一个对象中。然而,当涉及嵌套对象或多层级结构时,扩展运算符会遇到限制。它只能复制对象的第一层属性,而无法递归地复制嵌套的对象。

(分配方式:someOtherVar = someVar)
下面我们来看一下展开运算符在处理嵌套对象的复杂性时,并不如预期。对于嵌套对象来说,扩展运算符只提供了第一层属性的深拷贝,而对于所有嵌套的数据来说,它们与原始数据共享内存空间,实际上进行的是浅拷贝。

Population.total 在 city 和shallowCity 中共享一个内存点。扩展运算符获取顶层数据并将其添加到单独的内存空间;因此,shallowCity 的 name 属性实际上已更改。
对深对象进行深拷[JSON.parse(JSON.stringify())]
为了解决嵌套对象的复杂性问题,下面向大家介绍如何在深对象中进行深拷贝。在 JavaScript 中,当需要复制嵌套对象或数组时,深拷贝变得非常重要。深拷贝是一种创建独立全新对象的方法,它递归地复制每个嵌套对象和数组,有效地避免了使用共享内存带来的修改问题。其中,最常用的深拷贝方法是使用JSON.parse(JSON.stringify(object))。该方法首先将原始对象序列化为 JSON 字符串,然后再解析字符串并创建一个新对象,以确保所有属性和嵌套对象都被复制到全新的对象中。当然,需要注意的是该方法存在一定的局限性,例如无法复制函数、正则表达式等非数据类型,并且在某些情况下可能会带来性能问题。因此,在实际应用中,我们必须根据具体情况选择适合的深拷贝方法,以取得效率和正确性的平衡。

(对深对象进行深拷贝)
总结
JavaScript中的浅拷贝复制对象是创建一个新对象,但嵌套对象仍然共享内存。而深拷贝则创建一个独立的全新对象,包括嵌套对象在内都被完全复制。浅拷贝常用方法有Object.assign()和扩展运算符,而深拷贝可以使用JSON.parse(JSON.stringify())或第三方库。深拷贝适用于修改副本且不影响原始对象的情况,但可能消耗更多资源和时间。了解这两种拷贝方式的差异和应用场景是编写健壮代码的关键。
JavaScript中的浅拷贝与深拷贝的更多相关文章
- Javascript中的浅拷贝和深拷贝
很多开发语言中都有浅拷贝和深拷贝的说法,这里简单区分一下它们在Javascript中的区别,以及jQuery中深拷贝的实现. 在谈浅拷贝和深拷贝之前,先要屡清楚Javascript中的按值访问和按引用 ...
- javascript中的浅拷贝和深拷贝(拷贝引用和拷贝实例)
作者:千锋教育链接:https://www.zhihu.com/question/23031215/answer/326129003来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- javascript中的浅拷贝和深拷贝 分类: JavaScript 2015-05-07 15:29 831人阅读 评论(1) 收藏
1.js对象浅拷贝 简单的赋值就是浅拷贝.因为对象和数组在赋值的时候都是引用传递.赋值的时候只是传递一个指针. 看下面的实例代码: var a = [1,2,3]; var b =a ; var te ...
- 【转】JAVA中的浅拷贝和深拷贝
原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...
- javascript中的堆栈、深拷贝和浅拷贝、闭包
堆栈 在javascript中,堆内存是用来存放引用类型的空间环境 而栈内存,是存储基本类型和指定代码的环境 在对象中的属性名具有唯一性,数字属性名=字符串属性名,但是在测试的时候你会发现,好像所有属 ...
- javascript中的浅拷贝ShallowCopy与深拷贝DeepCopy
拷贝,在js中,分为浅拷贝和深拷贝.这两者是如何区分的呢?又是如何实现的呢? 深浅拷贝的区分 首先说下,在js中,分为基础数据类型和复杂数据类型, 基础数据类型:Undefined.Null.Bool ...
- js中的浅拷贝和深拷贝
说说最近所学:浅拷贝和深拷贝也叫做浅克隆和深克隆,深浅主要针对的是对象的"深度",常见的对象都是"浅"的,也就是对象里的属性就是单个的属性,而"深&q ...
- 浅谈JS中的浅拷贝与深拷贝
前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙地运 ...
- C# 中的浅拷贝与深拷贝
Ø 简介 在 C# 中分为两种数据类型,值类型和引用类型.我们知道,值类型之间赋值是直接将值赋值给另一个变量,两个变量值的改变都互不影响:而引用类型赋值则是将引用赋值给另一个变量,其中一个变量中的成 ...
- Javascript/js 的浅拷贝与深拷贝(复制)学习随笔
js变量的数据类型值分基本类型值和引用类型值. 在ES6(ECMAScript6)以前,基本数据类型包括String.Number.Boolean.Undefined.Null. 基本类型值的复制(拷 ...
随机推荐
- 使用 Docker 分析高通量测序数据
端午节假期,先祝各位 Bio IT 的爱好者们,节日快乐! 做生信的童鞋想要学习 Docker,或者使用 Docker+Pipeline 封装自己的一套数据分析流程,相信一定不能错过胡博强老师在201 ...
- 2023-06-21:redis中什么是BigKey?该如何解决?
2023-06-21:redis中什么是BigKey?该如何解决? 答案2023-06-21: 什么是bigkey bigkey是指存储在Key-Value数据库中的键对应的值所占用的内存空间较大.举 ...
- 第二章 VM与Linux的安装
1. VMWare 安装 2. CentOS 安装 安装网址:https://blog.csdn.net/qq_41819965/article/details/11118 ...
- 文件系统考古 3:1994 - The SGI XFS Filesystem
在 1994 年,论文<XFS 文件系统的可扩展性>发表了.自 1984 年以来,计算机的发展速度变得更快,存储容量也增加了.值得注意的是,在这个时期出现了更多配备多个 CPU 的计算机, ...
- 【翻译】rocksdb write stall
翻译自官方wiki:https://github.com/facebook/rocksdb/wiki/Write-Stalls 转载请注明出处:https://www.cnblogs.com/morn ...
- 【Oracle】行转列的函数wm_concat,listagg,xmlagg,pivot以及动态行转列
[Oracle]行转列的几种情况 表的数据如下 朴实无华的函数 1.wm_concat 使用格式: select 分组字段,wm_concat(要转换的列名) from 表名 group by 分组字 ...
- vue3中父组件与组件之间参数传递,使用(defineProps/defineEmits),涉及属性传递,对象传递,数组传递,以及事件传递
Vue3 中子父组件之间的通信 一.父组件传递参数到子组件 采用defineProps 传递属性 父组件: <template> <div> <h1>这是父组件&l ...
- .NET 8 Preview 6发布,支持新的了Blazor呈现方案 和 VS Code .NET MAUI 扩展
2023年7月11日 .NET 8 Preview 6,.NET 团队在官方博客发布了系列文章: Announcing .NET 8 Preview 6[1] ASP.NET Core updates ...
- Excel 进度图表制作
Excel 改变图标的形状 最终效果 过程有点杂乱,不再重新整理,基本照着下面的设就完事了. 未完成的想用柱型,和已完成的相结合 右击,更改表类型 选择簇状柱形图.次标轴 注意主.次坐标 进度改为折线 ...
- 活动干货|泛娱乐App出海东南亚深度解析
泛娱乐社交出海,还有哪些机会点? 为助力出海企业把握增长红利,即构科技特开设<出海"构"有料--泛娱乐出海系列直播>,从热门国家的特性洞察.玩法解决方案到技术服务经验分 ...