js 浅拷贝和深拷贝的区别和应用
在 JavaScript 中,浅拷贝和深拷贝都用于复制对象的内容,但它们在复制的方式和效果上有显著的区别。理解它们的差异对于避免常见的 bug 和正确使用数据结构非常重要。
1. 浅拷贝(Shallow Copy)
浅拷贝是指创建一个新的对象,但新的对象中仅复制原始对象的第一层属性(即原始对象的属性值)。如果属性值本身是一个对象或数组,那么它不会被复制,而是会保留对原始对象属性的引用。
特点:
- 浅拷贝只复制对象的“第一层”属性,对于属性值是对象或数组的情况,它们仍然指向原始对象的引用。
- 这样修改拷贝对象中的嵌套对象会影响到原始对象中的嵌套对象。
例子:
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj }; // 使用扩展运算符进行浅拷贝
shallowCopy.a = 10; // 修改第一层的属性
shallowCopy.b.c = 20; // 修改嵌套对象中的属性
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(shallowCopy); // { a: 10, b: { c: 20 } }
解释:
shallowCopy.a = 10
只改变了第一层属性a
的值,原始对象obj
中的a
仍然是1
。shallowCopy.b.c = 20
影响了b
这个嵌套对象,因为它们仍然引用了同一个对象。
常见的浅拷贝方法:
- 使用
Object.assign()
:const shallowCopy = Object.assign({}, obj);
- 使用扩展运算符(
...
):const shallowCopy = { ...obj };
2. 深拷贝(Deep Copy)
深拷贝是指创建一个新的对象,并且递归地复制原始对象的所有属性,不管这些属性的值是原始类型(如字符串、数字、布尔值等),还是引用类型(如对象、数组等)。深拷贝会完全独立于原始对象,因此修改新对象中的属性不会影响原始对象。
特点:
- 深拷贝会复制对象的所有层级,包括嵌套的对象或数组,确保没有任何引用关系。
- 修改深拷贝后的对象,不会影响原始对象。
例子:
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj)); // 使用 JSON 方法进行深拷贝
deepCopy.a = 10;
deepCopy.b.c = 20;
console.log(obj); // { a: 1, b: { c: 2 } }
console.log(deepCopy); // { a: 10, b: { c: 20 } }
解释:
deepCopy
是通过JSON.parse(JSON.stringify())
实现的深拷贝,这种方法可以确保obj
中的每一层都被复制,并且是完全独立的。- 修改
deepCopy
中的属性a
和b.c
不会影响obj
,因为它们不再共享引用。
常见的深拷贝方法:
- 使用
JSON.parse(JSON.stringify(obj))
(但有局限性,不能复制函数、undefined
、Symbol
等,且无法处理循环引用)。 - 使用递归方法手动实现深拷贝。
- 使用第三方库(如
Lodash
的cloneDeep
方法)。
// 使用 Lodash 的 deep clone 方法
const _ = require('lodash');
const deepCopy = _.cloneDeep(obj);
3. 浅拷贝与深拷贝的区别总结
特性 | 浅拷贝 | 深拷贝 |
---|---|---|
复制深度 | 仅复制一层(第一层)属性 | 递归复制所有层级的属性 |
对引用类型的处理 | 仅复制引用类型的引用 | 复制引用类型的内容,完全独立 |
修改结果 | 修改嵌套对象会影响原始对象 | 修改拷贝对象不会影响原始对象 |
常见方法 | Object.assign() 、扩展运算符(... ) |
JSON.parse(JSON.stringify()) 、手动递归、Lodash.cloneDeep() |
4. 浅拷贝和深拷贝的应用场景
-
浅拷贝:
- 用于复制对象的第一层属性,但不需要复制嵌套对象。适用于仅需要修改一层数据的场景。
- 在组件状态管理中,如果对象的嵌套属性没有被修改,浅拷贝可以避免不必要的深度复制,提高性能。
-
深拷贝:
- 用于确保对象之间完全独立,特别是当对象中包含嵌套的引用类型(如数组或对象),且这些嵌套对象需要独立修改时。
- 在需要避免对原始数据进行修改(如在状态管理中,或者操作不可变数据时)非常有用。
总结
- 浅拷贝适用于只需要复制对象的第一层属性的场景,且不会影响引用类型的修改。
- 深拷贝适用于需要确保完全独立的对象副本,尤其是在对象中包含嵌套引用类型时。
根据不同的应用场景选择适当的拷贝方式,能有效提高代码的效率和可靠性。
相信坚持的力量,日复一日的习惯.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· Qt个人项目总结 —— MySQL数据库查询与断言
2022-11-08 /etc/profile、/etc/bashrc、~/.bash_profile、~/.bashrc 文件的作用
2022-11-08 linux java 安装
2022-11-08 tomcat 各个版本下载地址
2018-11-08 获取具体地址的经纬度
2017-11-08 array_unique后,数组本身的值并不会变
2017-11-08 rename table table1 to table2;