深拷贝浅拷贝是什么?
在 JavaScript 开发中,深拷贝和浅拷贝是处理对象和数组的常见操作。它们涉及到复制数据结构以及处理引用类型数据的方式。
深拷贝和浅拷贝在不同的场景中有各自的应用。浅拷贝适用于简单的数据结构,当我们只需要复制基本数据类型的值或者共享引用类型数据时。而深拷贝则适用于需要完全独立的副本,以避免原始数据的修改对拷贝对象造成影响的情况。
1.浅拷贝
定义:浅拷贝是指创建一个新对象,这个新对象对原始对象的属性进行逐一复制。如果属性是基本类型(如字符串、数字、布尔值等),则复制的是值。如果属性是引用类型(如对象、数组),则复制的是引用。这意味着拷贝的新对象和原始对象共享同一个引用类型的属性。
1.1常见的浅拷贝方法:
Object.assign
:
const original = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, original);
copy.b.c = 3;
console.log(original.b.c); // 输出: 3
console.log(copy.b.c); // 输出: 3
扩展运算符(Spread Operator):
const original = { a: 1, b: { c: 2 } };
const copy = { ...original };
copy.b.c = 3;
console.log(original.b.c); // 输出: 3
console.log(copy.b.c); // 输出: 3
Array.prototype.slice
(用于数组):
const original = [1, 2, { a: 3 }];
const copy = original.slice();
copy[2].a = 4;
console.log(original[2].a); // 输出: 4
console.log(copy[2].a); // 输出: 4
2.深拷贝
定义:深拷贝是指创建一个新对象,新对象完全复制原始对象的所有属性,包括嵌套的对象和数组。深拷贝后的新对象与原始对象完全独立,修改新对象的属性不会影响原始对象,反之亦然。
2.1深拷贝的方法:
JSON.parse
和 JSON.stringify
:
const original = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(original));
copy.b.c = 3;
console.log(original.b.c); // 输出: 2
console.log(copy.b.c); // 输出: 3
- 优点:简单易用。
- 缺点:不能拷贝函数、
undefined
、Symbol
,且无法处理循环引用。
递归方法:
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (Array.isArray(obj)) {
const copy = [];
for (let i = 0; i < obj.length; i++) {
copy[i] = deepClone(obj[i]);
}
return copy;
}
const copy = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepClone(obj[key]);
}
}
return copy;
}
const original = { a: 1, b: { c: 2 } };
const copy = deepClone(original);
copy.b.c = 3;
console.log(original.b.c); // 输出: 2
console.log(copy.b.c); // 输出: 3
使用第三方库(如 lodash
的 cloneDeep
方法):
const _ = require('lodash');
const original = { a: 1, b: { c: 2 } };
const copy = _.cloneDeep(original);
copy.b.c = 3;
console.log(original.b.c); // 输出: 2
console.log(copy.b.c); // 输出: 3
3.浅拷贝和深拷贝的区别
-
复制的深度:
- 浅拷贝:只复制对象或数组的顶层属性,嵌套对象或数组只是引用。
- 深拷贝:递归地复制所有层级的属性,嵌套对象或数组也会被完全复制。
-
独立性:
- 浅拷贝:新对象和原始对象共享嵌套对象或数组的引用,修改一个会影响另一个。
- 深拷贝:新对象与原始对象完全独立,修改一个不会影响另一个。
4.作用场景
-
. 浅拷贝适用场景:
- 属性层级较浅的对象或数组。
- 不担心嵌套对象或数组共享引用的情况。
- 性能要求较高的场景,浅拷贝的性能开销较小。
-
. 深拷贝适用场景:
- 属性层级较深的对象或数组。
- 需要完全独立的副本,防止原始对象和新对象之间的相互影响。
- 需要处理复杂对象结构,包括嵌套对象、数组和循环引用的情况。
总结
浅拷贝和深拷贝在 JavaScript 中是两种常见的对象或数组复制方式。浅拷贝只复制对象或数组的顶层属性,而深拷贝会递归地复制所有嵌套的属性。选择使用哪种拷贝方式取决于具体的应用场景和性能要求。理解它们的区别和适用场景,有助于编写更健壮和高效的代码。