每天做个总结吧,坚持就是胜利!
/**
@date 2021-06-13
@description 深拷贝
*/
壹(序)
浅拷贝与深拷贝:
在js中,拷贝引用数据类型
时,如果此引用数据(假设为obj
)中引用了另一个引用(假设为childObj
),那么浅拷贝只会拷贝childObj
的引用地址
,也就是说如果改变
了childObj
里面的值,那么新的
拷贝对象中的childObj
也会改变
;而深拷贝是将所有值
都进行复制,即使是引用数据类型,也会重新声明
一个新的对象,不会存在改变了原数据内的数据而影响
拷贝数据的现象。
贰(代码实现)
// 判断是否是一个object
const isObject = (target) => {
return typeof target === "object" && target !== null;
};
// 深拷贝
const cloneDeep = (target, hash = new WeakMap()) => {
// 基本数据类型则直接返回
if (!isObject(target)) {
return target;
}
// 定义一个hashMap,如果hashMap中存在的话,直接返回,用来解决两个对象相互引用的情况
if (hash.has(target)) {
return hash.get(target);
}
// 定义拷贝后的对象
const cloneTarget = Array.isArray(target) ? [] : {};
// 向hashMap中插入值
hash.set(target, cloneTarget);
// 处理symbol情况
const symKeys = Object.getOwnPropertySymbols(target);
symKeys.forEach((item) => {
const symTarget = target[item];
if (isObject(symTarget)) {
cloneTarget[item] = cloneDeep(symTarget, hash);
} else {
cloneTarget[item] = symTarget;
}
});
// 非symbol
const keys = Object.keys(target);
keys.forEach((key) => {
const objTarget = target[key];
if (isObject(objTarget)) {
cloneTarget[key] = cloneDeep(objTarget, hash);
} else {
cloneTarget[key] = objTarget;
}
});
return cloneTarget;
};
// 测试
const childObj = { c: 3 };
const obj = { a: 1, b: 2, childObj };
obj.childObj = obj;
const sym = Symbol("test");
obj[sym] = 3;
console.log(obj); // {a: 1, b: 2, childObj: {…}, Symbol(test): 3}
const newObj = cloneDeep(obj);
console.log(newObj); // {a: 1, b: 2, childObj: {…}, Symbol(test): 3}
obj.a = 4;
obj[sym] = 5;
console.log(obj); // {a: 4, b: 2, childObj: {…}, Symbol(test): 5}
console.log(newObj); // {a: 1, b: 2, childObj: {…}, Symbol(test): 3}
const arr = [1, 2, {a: 3}];
const newArr = cloneDeep(arr);
console.log(arr); // [1 ,2 ,{a: 3}]
console.log(newArr); // [1 ,2 ,{a: 3}]
arr[0] = 4;
arr[2].a = 5;
console.log(arr); // [4 ,2 ,{a: 5}]
console.log(newArr); // [1 ,2 ,{a: 3}]
叁(结语欧)
大家端午安康!