定义
在 JavaScript 中,深拷贝和浅拷贝是针对引用数据类型(如对象和数组)的复制方式。它们的主要区别在于是否创建新的内存空间。
核心特点
- 浅拷贝 (Shallow Copy):
- 只复制指向对象的指针,而不复制对象本身。
- 新对象和原对象共享同一块内存空间。
- 修改新对象会影响原对象,反之亦然。
- 深拷贝 (Deep Copy):
- 创建一个全新的对象,复制原对象的所有属性和值。
- 新对象和原对象拥有独立的内存空间。
- 修改新对象不会影响原对象,反之亦然。
浅拷贝的实现方式
- Object.assign():只能拷贝第一层属性,如果属性是对象或数组,仍然是浅拷贝。
- 展开运算符 (…):与
Object.assign()
类似,只能拷贝第一层属性。
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.a = 3;
shallowCopy.b.c = 4;
console.log(obj.a); // 1
console.log(obj.b.c); // 4
深拷贝的实现方式
- JSON.parse(JSON.stringify(obj)):
- 简单粗暴,但有局限性:
- 无法拷贝函数、Symbol、undefined。
- Date 对象会被转换为字符串。
- 循环引用会报错。
- 简单粗暴,但有局限性:
- 递归实现:
- 可以处理各种数据类型,包括函数、Symbol、Date 等。
- 需要考虑循环引用的问题。
function deepCopy(obj, cache = new WeakMap()) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (cache.has(obj)) {
return cache.get(obj); // 解决循环引用
}
const copy = Array.isArray(obj) ? [] : {};
cache.set(obj, copy);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key], cache);
}
}
return copy;
}
const obj = { a: 1, b: { c: 2 }, d: new Date() };
const deepCopyObj = deepCopy(obj);
deepCopyObj.a = 3;
deepCopyObj.b.c = 4;
console.log(obj.a); // 1
console.log(obj.b.c); // 2
应用场景
- 浅拷贝:
- 复制简单对象或数组,且不需要修改原对象。
- 例如:复制配置对象。
- 深拷贝:
- 复制复杂对象或数组,且需要修改新对象而不影响原对象。
- 例如:复制用户数据、游戏状态。
优缺点
- 浅拷贝:
- 优点:速度快,内存占用少。
- 缺点:修改新对象会影响原对象。
- 深拷贝:
- 优点:修改新对象不会影响原对象。
- 缺点:速度慢,内存占用多。
相关概念
参考资料