说说你对深浅拷贝的理解?并实现一个对数组和对象深拷贝的方法
深浅拷贝的理解 (前端开发)
在 JavaScript 中,赋值操作、浅拷贝和深拷贝都是复制数据的不同方式,它们对原始值和引用值(对象、数组)的处理方式不同,导致结果差异很大。
1. 赋值:
- 只是简单地创建了一个指向相同内存地址的指针。修改其中一个变量会影响另一个变量,因为它们指向同一个数据。
- 适用于原始值(数字、字符串、布尔值、null、undefined、Symbol),因为它们的值存储在变量本身。
- 对引用值来说,赋值只是复制了引用,而不是数据本身。
2. 浅拷贝:
- 创建了一个新的变量,并将原始值的属性值复制到新变量中。
- 对于原始值,浅拷贝和赋值的效果相同。
- 对于引用值,浅拷贝只复制了对象的第一层属性。如果属性是原始值,则复制值;如果属性是引用值,则复制引用,这意味着修改新变量的嵌套属性会影响原始变量。
3. 深拷贝:
- 创建了一个全新的变量,并将原始值及其所有嵌套属性的值都递归地复制到新变量中。
- 对于原始值,深拷贝和赋值/浅拷贝的效果相同。
- 对于引用值,深拷贝会创建一个完全独立的副本,修改新变量不会影响原始变量,反之亦然。
深拷贝方法实现 (前端开发)
以下是一个通用的深拷贝函数 deepClone
,可以处理数组和对象,并递归处理嵌套的引用值:
function deepClone(obj) {
// 处理 null、undefined 和原始值
if (typeof obj !== "object" || obj === null) {
return obj;
}
// 创建新对象或数组
const clonedObj = Array.isArray(obj) ? [] : {};
// 递归复制属性
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
// 测试用例
const originalArray = [1, 2, { a: 3, b: [4, 5] }];
const clonedArray = deepClone(originalArray);
clonedArray[2].a = 6;
clonedArray[2].b.push(6);
console.log("Original Array:", originalArray);
console.log("Cloned Array:", clonedArray);
const originalObject = { a: 1, b: { c: 2, d: [3, 4] } };
const clonedObject = deepClone(originalObject);
clonedObject.b.c = 5;
clonedObject.b.d.push(5);
console.log("Original Object:", originalObject);
console.log("Cloned Object:", clonedObject);
// 处理循环引用 (简化版,更健壮的方案需要使用 WeakMap)
function deepCloneWithCycleCheck(obj, seen = new Set()) {
if (typeof obj !== "object" || obj === null || seen.has(obj)) {
return obj;
}
seen.add(obj);
const clonedObj = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepCloneWithCycleCheck(obj[key], seen);
}
}
return clonedObj;
}
const objWithCycle = { a: 1 };
objWithCycle.b = objWithCycle;
const clonedObjWithCycle = deepCloneWithCycleCheck(objWithCycle);
console.log("Original Object with Cycle:", objWithCycle);
console.log("Cloned Object with Cycle:", clonedObjWithCycle);
关键点:
- 使用递归处理嵌套对象和数组。
- 使用
hasOwnProperty
确保只复制对象自身的属性,而不是原型链上的属性。 - 区分数组和对象,创建对应的空数组或空对象。
- 添加了
deepCloneWithCycleCheck
函数来简要展示如何处理循环引用,更完善的循环引用处理需要更复杂的逻辑,例如使用WeakMap
来跟踪已访问的对象。
这个 deepClone
函数提供了一个基本的深拷贝实现。对于更复杂的数据结构(例如包含日期、正则表达式、函数等),需要进行额外的处理。 一些库,例如 Lodash 的 cloneDeep
函数,提供了更强大和全面的深拷贝功能。 根据你的具体需求
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY