1、【特殊点】WeakMap 只接受引用类型(对象)作为键名; 2、【优点】WeakMap 的键名所指向的对象都是弱引用,不计入垃圾回收机制,不用考虑内存泄漏。 当引用对象被清除,其所对应的 WeakMap 记录就会自动被移除。
const shallClone = (target) => {
if (typeof target === "object" && target !== null) {
const cloneTarget = Array.isArray(target) ? [] : {};
for (let prop in target) {
if (target.hasOwnProperty(prop)) {
// 遍历对象自身可枚举属性(不考虑继承属性和原型对象)
cloneTarget[prop] = target[prop];
}
}
return cloneTarget;
} else {
return target;
}
};
/**
* 深克隆(深拷贝)+ 解决深拷贝函数中循环引用时导致的栈溢出的问题
* @param {object} origin
* @param {*} hashMap WeakMap数据,用于缓存克隆过的对象
* @returns origin / 克隆的origin
*/
function deepCloneCycle(origin, hashMap = new WeakMap()) {
let result = null;
if (hashMap.has(origin)) return hashMap.get(origin); // 查缓存字典中是否已有需要克隆的对象,有的话直接返回同一个对象(同一个引用,不用递归无限创建进而导致栈溢出了);
// typeof null === 'object' true
// typeof [] === 'object' true
// typeof NaN === 'object' false
if (typeof origin === "object" && origin !== null) {
// 【类型判断】引用类型,进行递归拷贝(用typeof判断类型要剔除null的情况)
if (Object.prototype.toString.call(origin) === "[object Array]") {
// 【类型判断】数组类型,创建一个新数组
result = [];
hashMap.set(origin, result); // 哈希表缓存新值
// 【遍历赋值】
origin.forEach((el) => {
result.push(deepCloneCycle(el, hashMap)); // 【递归】
});
} else if (Object.prototype.toString.call(origin) === "[object Object]") {
// 【类型判断】对象类型,创建一个新对象
result = {};
hashMap.set(origin, result); // 哈希表缓存新值
for (const key in origin) {
// 【遍历赋值】对象这里特殊处理了,不遍历拷贝原型链上的属性
if (origin.hasOwnProperty(key)) {
result[key] = deepCloneCycle(origin[key], hashMap); // 【递归】
}
}
}
} else {
// 【类型判断】原始类型直接返回
return origin;
}
return result;
}