浅拷贝是创建⼀个新的对象,新对象的⼀些属性引⽤原始对象中相同的属性。这意味着在原始对象或新对象上的更改会相互
影响。
深拷贝是创建⼀个新的对象,并复制原始对象的所有属性,包括嵌套的对象和数组。这意味着在原始对象或新对象上的更改不会相互影响。
浅拷贝和深拷贝的主要差别在于对引用类型的处理。深拷贝会复制对象中的数据,因此修改深拷贝对象中的属性不会影响原对象中的属性。相反,浅拷贝仅复制引用,修改其中的属性会影响原对象的属性。同时也需要理解浅拷贝和赋值的区别,赋值对于对象中的基本类型采用引用其地址的方式,而浅拷贝会复制基本类型的数据。
浅拷贝可以使⽤Object.assgin()这个方法来拷贝。
// 原对象
const original = {
name: 'John',
address: {
city: 'New York',
state: 'NY'
}
};
// 浅拷贝
const shallowCopy = Object.assign({}, original);
// 修改浅拷贝对象中的引用类型属性
shallowCopy.address.city = 'Chicago';
// 查看原对象的引用类型属性
console.log(original.address.city); // Output: Chicago
深拷贝通常可通过JSON.parse() 和 JSON.stringify() 实现
以下是通过此方法来实现深拷贝的代码:
// 定义一个包含嵌套对象的原始对象
const obj = { name: 'John', age: 30, address: { city: 'New York', state: 'NY' } };
// 使用深拷贝创建一个新的对象
const obj2 = JSON.parse(JSON.stringify(obj));
// 修改新对象中嵌套对象的属性
obj2.address.city = 'Chicago';
// 原始对象的嵌套对象属性未受影响
console.log(obj.address.city); // 输出:New York
// 新对象的嵌套对象属性已被修改
console.log(obj2.address.city); // 输出:Chicago
但此方法无法拷贝函数。为了解决函数拷贝的问题,递归成为一种常见的深拷贝方式。
以下是通过递归来实现深拷贝的代码:
/**
* 深拷贝函数,通过递归实现
* @param {*} target - 需要拷贝的对象
* @param {Map} map - 用于检测循环引用的映射表
* @returns {*} - 拷贝后的对象
*/
function clone(target, map = new Map()) {
// 判断目标是否为对象
if (typeof target === 'object') {
// 初始化克隆目标,数组和普通对象分别处理
let cloneTarget = Array.isArray(target) ? [] : {};
// 检查映射表中是否已有该对象,防止循环引用
if (map.get(target)) {
return map.get(target);
}
// 将当前对象添加到映射表
map.set(target, cloneTarget);
// 递归拷贝对象的每个属性
for (const key in target) {
cloneTarget[key] = clone(target[key], map);
}
// 返回拷贝后的对象
return cloneTarget;
} else {
// 如果不是对象,直接返回原始值
return target;
}
}
通过递归遍历对象的所有属性,对于属性值为对象的情况,递归调用深拷贝函数,确保每个嵌套的对象都得到正确的拷贝,防止循环引用。