以下是浅拷贝(Shallow Copy)和深拷贝(Deep Copy)的详细解释和对比:
一、核心区别
特性 | 浅拷贝 | 深拷贝 |
---|---|---|
复制层级 | 只复制对象的第一层属性(基本类型直接复制值,引用类型复制内存地址) | 递归复制对象的所有层级属性(包括嵌套对象、数组等),创建完全独立的副本 |
内存引用 | 嵌套的引用类型数据与原对象共享内存(修改会相互影响) | 所有层级数据与原对象完全独立(修改互不影响) |
适用场景 | 简单数据结构(无嵌套引用类型) | 复杂数据结构(包含嵌套对象、数组等) |
二、示例说明
1. 浅拷贝示例
const original = {
name: "Alice",
hobbies: ["reading", "music"]
};
// 浅拷贝方法:展开运算符
const shallowCopy = { ...original };
// 修改浅拷贝的顶层属性
shallowCopy.name = "Bob";
console.log(original.name); // "Alice"(原对象未受影响)
// 修改浅拷贝的嵌套引用属性
shallowCopy.hobbies.push("coding");
console.log(original.hobbies); // ["reading", "music", "coding"] ❌ 原对象被影响!
2. 深拷贝示例
const original = {
name: "Alice",
hobbies: ["reading", "music"]
};
// 深拷贝方法:JSON 序列化(有局限性,见下文)
const deepCopy = JSON.parse(JSON.stringify(original));
// 修改深拷贝的嵌套属性
deepCopy.hobbies.push("coding");
console.log(original.hobbies); // ["reading", "music"] ✅ 原对象不受影响!
三、实现方式
1. 浅拷贝方法
方法 | 示例 | 适用场景 |
---|---|---|
展开运算符 ... | const copy = { ...obj }; | 对象/数组的浅拷贝 |
Object.assign() | const copy = Object.assign({}, obj); | 对象的浅拷贝 |
Array.slice() | const copy = arr.slice(); | 数组的浅拷贝 |
Array.concat() | const copy = [].concat(arr); | 数组的浅拷贝 |
2. 深拷贝方法
方法 | 示例 | 优缺点 |
---|---|---|
JSON.parse(JSON.stringify()) | const copy = JSON.parse(JSON.stringify(obj)); | ✅ 简单<br/>❌ 无法处理函数、undefined 、循环引用、Date 对象等 |
第三方库(如 lodash) | _.cloneDeep(obj); | ✅ 处理复杂对象<br/>❌ 需引入外部库 |
手动递归实现 | 自定义递归函数遍历所有属性 | ✅ 完全控制<br/>❌ 代码复杂,需处理边界条件 |
四、深拷贝的手动实现
function deepClone(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] = deepClone(obj[key]); // 递归拷贝
}
}
return copy;
}
// 使用示例
const original = { a: 1, b: { c: 2 } };
const deepCopy = deepClone(original);
五、注意事项
-
性能问题:
- 深拷贝比浅拷贝更耗资源(尤其是大型对象)。
- 避免在频繁操作中使用深拷贝。
-
特殊数据类型:
Date
、RegExp
、Function
等需要特殊处理(JSON 方法会丢失信息)。
-
循环引用:
- 当对象属性间接引用自身时,JSON 方法和简单递归会报错,需额外处理。
六、总结
操作 | 是否共享内存 | 修改嵌套数据的影响 | 复杂度 |
---|---|---|---|
直接赋值 | ✅ 是 | 相互影响 | 无 |
浅拷贝 | ✅ 是(仅嵌套层) | 嵌套数据相互影响 | 低 |
深拷贝 | ❌ 否 | 完全独立 | 高 |