js 深浅拷贝
在JavaScript中,我们经常需要复制一个对象或者数组,这就涉及到了深拷贝和浅拷贝的概念。深拷贝和浅拷贝是对数据的复制方式的描述,了解它们的区别对于我们正确处理数据非常重要。
浅拷贝
浅拷贝是指将一个对象或数组复制给一个新的变量,但只复制了对象或数组的第一层内容,如果对象或数组中还包含了对象或数组,那么直接复制的是引用,而不是实际值。
举个示例,我们定义一个对象和一个数组:
let obj = {a: 1, b: {c: 2}};
let arr = [1, 2, [3, 4]];
接着我们使用浅拷贝来复制这两个数据:
let objCopy = Object.assign({}, obj);
let arrCopy = arr.slice();
现在我们修改原始数据中的第二层对象或数组:
obj.b.c = 3;
arr[2][0] = 5;
看看原始数据和拷贝数据的变化:
console.log(obj); // {a: 1, b: {c: 3}}
console.log(objCopy); // {a: 1, b: {c: 3}}
console.log(arr); // [1, 2, [5, 4]]
console.log(arrCopy); // [1, 2, [5, 4]]
从示例中可以看出,由于浅拷贝只复制了第一层的值,所以修改原始数据的第二层内容也会影响到拷贝的数据。这是因为浅拷贝只是复制了引用,所以两个数据指向同一个内存地址。
深拷贝
深拷贝是指将一个对象或数组以及其包含的所有子对象或子数组都完全复制一份,新的数据和原始数据完全独立,互不影响。
实现深拷贝有很多种方法,下面介绍几种常用的方法。
方法一:递归实现深拷贝
通过递归遍历对象或数组,逐层复制值,来实现深拷贝。
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
我们使用这个方法来深拷贝一个对象和数组:
let obj = {a: 1, b: {c: 2}};
let arr = [1, 2, [3, 4]];
let objCopy = deepClone(obj);
let arrCopy = deepClone(arr);
现在我们修改原始数据中的第二层对象或数组:
obj.b.c = 3;
arr[2][0] = 5;
查看原始数据和拷贝数据的变化:
console.log(obj); // {a: 1, b: {c: 3}}
console.log(objCopy); // {a: 1, b: {c: 2}}
console.log(arr); // [1, 2, [5, 4]]
console.log(arrCopy); // [1, 2, [3, 4]]
通过递归实现深拷贝,我们可以看到修改原始数据不会影响到拷贝数据,它们是完全独立的。
方法二:JSON序列化/反序列化
另一种实现深拷贝的简单方法是使用JSON的序列化和反序列化。
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
需要注意的是,使用JSON的方法实现深拷贝有一些局限性:
- 无法处理循环引用,会导致报错
- 会忽略 undefined、symbol、函数
总结
深拷贝和浅拷贝在处理数据时有着不同的表现,正确选择适合的拷贝方式非常重要。浅拷贝只复制第一层数据,而深拷贝会递归复制所有子对象或子数组。在实际开发中,根据数据的复杂度和需求来选择合适的拷贝方式。