原理:深拷贝 = 浅拷贝 + 递归。在浅拷贝的基础上判断当前属性值是简单类型还是引用类型。如果是简单类型直接赋值,如果是引用类型,递归操作。
function isObject(obj) { // 判断属性值是否为引用类型
return typeof obj === 'object' && obj != null;
}
function cloneDeep(target, hash = new WeakMap()) {
if (!isObject(target)) return target;
const results = Array.isArray(target) ? [] : {}; // 兼容数组类型
if (hash.has(target)) return hash.get(target); // 解决引用丢失的问题和循环引用的问题
hash.set(target, results);
const symkeys = Object.getOwnPropertySymbols(target); // 获取symbol类型的键
if (symkeys.length) {
syskeys.forEach(item => { // 拷贝symbol类型属性的值
if (isObject(target[item])) {
results[item] = cloneDeep(target[item], hash); } else {
results[item] = target[item]
}
})
}
for (const k in target) { // 拷贝非Symbol类型属性的值
if (Object.prototype.hasOwnproperty.call(target, k)) {
if (isObject(target[k])) {
results[k] = cloneDeep(target[k], hash); } else {
results[k] = target[k];
}
}
}
return results;
}