JavaScript中的对象拷贝是我们在日常开发中经常遇到的一个问题。深浅拷贝是两种常见的拷贝方式,它们分别适用于不同的场景。本文将深入探讨JavaScript中浅拷贝和深拷贝的概念、区别以及实现方式。
浅拷贝是指将一个对象的属性值复制到另一个对象,如果属性值是基本数据类型(如数字、字符串、布尔等),则直接复制该值;如果属性值是引用数据类型(如对象、数组等),则复制的是其引用地址,而不是实际的对象本身。
let source = { name: '李华', age: 30 };
let shallowCopy = Object.assign({}, source);
let source = { name: '李华', age: 30 };
let shallowCopy = { ...source };
let array = [1, 2, 3];
let shallowCopy = array.concat();
深拷贝是指将一个对象从堆内存中完全复制一份到栈内存中,新对象与原对象是完全独立的,修改新对象不会影响原对象。
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepCopy(obj[key]);
}
}
return result;
}
let source = { name: '李华', age: 30 };
let deepCopy = JSON.parse(JSON.stringify(source));
// 引入Lodash
const _ = require('lodash');
// 原始对象
const originalObject = {
name: '李华',
age: 30,
nestedObject: {
sex: '男',
country: '中国'
}
};
// 使用Lodash的深拷贝函数 _.cloneDeep()
const deepCopyObject = _.cloneDeep(originalObject);
// 修改拷贝对象的某些属性
deepCopyObject.name = '李明';
deepCopyObject.nestedObject.sex= '女';
// 打印原始对象和拷贝对象,观察是否相互影响
console.log('原始对象:', originalObject);
console.log('深拷贝对象:', deepCopyObject);
// 原始对象
const originalObject = {
name: '李华',
age: 30,
nestedObject: {
sex: '男',
country: '中国'
}
};
// 使用 jQuery.extend() 进行深拷贝
var deepCopyObject = jQuery.extend(true, {}, originalObject);
// 修改拷贝对象的某些属性
deepCopyObject.name = '李明';
deepCopyObject.nestedObject.sex= '女';
// 打印原始对象和拷贝对象,观察是否相互影响
console.log('原始对象:', originalObject);
console.log('深拷贝对象:', deepCopyObject);
// 引入 Immer
import produce from 'immer';
// 原始对象
const originalObject = {
name: '李华',
age: 30,
nestedObject: {
sex: '男',
country: '中国'
}
};
// 使用 Immer 的 produce 函数进行深拷贝
const deepCopyObject = produce(originalObject, draft => {
// 修改 draft 对象的某些属性
draft.name = '李明';
draft.nestedObject.sex= '女';
});
// 打印原始对象和拷贝对象,观察是否相互影响
console.log('原始对象:', originalObject);
console.log('深拷贝对象:', deepCopyObject);
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj; // 如果是基本数据类型或 null,直接返回
}
// 根据原始对象的类型创建一个新的对象或数组
const copy = Array.isArray(obj) ? [] : {};
// 遍历原始对象的属性
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 递归深拷贝嵌套对象或数组
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
// 原始对象
const originalObject = {
name: '李华',
age: 30,
nestedObject: {
sex: '男',
country: '中国'
}
};
// 深拷贝对象
const deepCopyObject = deepCopy(originalObject);
// 修改拷贝对象的某些属性
deepCopyObject.name = '李明';
deepCopyObject.nestedObject.sex= '女';
// 打印原始对象和拷贝对象,观察是否相互影响
console.log('原始对象:', originalObject);
console.log('深拷贝对象:', deepCopyObject);
1.对于基本数据类型:
2.对于引用数据类型:
优点:
缺点:
性能开销: 深拷贝涉及递归复制整个对象树,性能开销相对较大,特别是在处理大型对象时。
实现复杂: 实现一个通用且高效的深拷贝函数相对复杂,需要处理循环引用、特殊对象类型等情况,避免出现死循环或遗漏某些情况。
优点:
性能较好: 浅拷贝通常比深拷贝的性能更好,因为它只复制对象的第一层属性,避免了递归复制整个对象树的开销。
简单易实现: 浅拷贝的实现方式相对简单,可以使用一些内建的方法或运算符(如Object.assign()、spread operator)来快速实现。
缺点:
在实际开发中,根据具体情况选择适当的拷贝方式,平衡性能和数据完整性,确保满足项目的需求。