我们都知道引用类型其实是在栈内存中存储了一个指针,这个指针指向堆内存中该对象的存储地址。复制给另一个对象的过程其实是把该对象的地址复制给了另一个对象变量,两个指针都指向同一个对象,所以若其中一个修改了,则另一个也会改变。
如果要解决这个问题,我们只能使用拷贝,今天我们就一起手写一个 cloneDeep
/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
* @returns
*/
function cloneDeep(obj) {
// obj 是 null,或者不是对象和数组,直接返回
if(typeof obj !== 'object' || obj == null) {
return obj;
}
// 初始化返回结果
let result;
if(obj instanceof Array) {
result = [];
} else {
result = {};
}
for (let key in obj) {
// 保证 key 不是原型的属性
if(obj.hasOwnProperty(key)) {
// 递归调用
result[key] = cloneDeep(obj[key]);
}
}
return result;
}
使用cloneDeep
// 对象
const obj = {"a": 1, "b": 2, "c": { "d": 3 }};
const obj1 = cloneDeep(obj);
obj1.c.d = 10
console.log(obj) // {"a": 1, "b": 2, "c": { "d": 3 }}
console.log(obj1) // {"a": 1, "b": 2, "c": { "d": 10 }};
// 数组
const arr = [{"a": 1, "b": 2, "c": {"d": 3}}, {"a": 2, "b": 3}];
const arr1 = cloneDeep(arr);
arr1[0].c.d = 10;
console.log(arr) // [{"a": 1, "b": 2, "c": {"d": 3}}, {"a": 2, "b": 3}]
console.log(arr1) // [{"a": 1, "b": 2, "c": {"d": 10}}, {"a": 2, "b": 3}]
网友评论