/**
* @desc 深拷贝函数
*/
function cloneDeep(obj, cache = new WeakMap()) {
// 如果该变量为非对象类型直接返回
if (obj === null || typeof obj !== 'object') {
return obj
}
// 如果是复杂类型,Date、RegExp类型的对象需要特殊处理下
if (obj instanceof Date) {
return new Date(obj);
}
if (obj instanceof RegExp) {
return new RegExp(obj);
}
// 特别注意循环引用的情况 a = {}; a.b = a; 为了避免这种情况,引入一个WeakMap来存储
if (cache.has(obj)) {
return cache.get(obj);
}
// 正常的处理情况,使用for... in遍历对象的key
// 创建一个新的空对象,为了保证原型链,调用一下构造函数
const cloneObj = new obj.constructor();
// 创建过的对象,往WeakMap中存一下
cache.set(obj, cloneObj);
for (key in obj) {
if (obj.hasOwnProperty(key)) {
// 属性有可能是对象类型,所以需要递归处理
cloneObj[key] = cloneDeep(obj[key], cache);
}
}
return cloneObj;
}
function deepClone(obj, cache = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
if (cache.has(obj)) return cache.get(obj) // 如果出现循环引用,则返回缓存的对象,防止递归进入死循环
let cloneObj = new obj.constructor() // 使用对象所属的构造函数创建一个新对象
cache.set(obj, cloneObj) // 缓存对象,用于循环引用的情况
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝
}
}
return cloneObj
}
// 测试
const obj = { name: 'Jack', address: { x: 100, y: 200 } }
obj.a = obj // 循环引用
const newObj = cloneDeep(obj)
console.log(newObj.address === obj.address) // false
console