JS递归实现深拷贝,通常使用函数递归的方式,对于嵌套数据结构进行深度遍历,对每个遍历到的数据进行判断,并进行相应的复制,从而实现数据对象的深复制。
/** * 递归实现深拷贝
* @param {any} obj 待拷贝的对象
* @param {Map} map 用于存储已经拷贝过的对象,避免循环引用
*/
function deepCopy(obj, map = new Map()) {
if (typeof obj !== 'object') {
return obj
}
// 处理各种对象类型,包括日期、正则、Map、Set等
let anyType = obj.constructor;
if (
anyType === RegExp ||
anyType === Date ||
anyType === Function ||
anyType === String ||
anyType === Number ||
anyType === Boolean ||
anyType === Symbol
) {
return new anyType(obj);
}
if (map.has(obj)) {
return map.get(obj)
}
let cloneObj = {}
switch (Object.prototype.toString.call(obj)) {
case '[Object Array]':
cloneObj = []
obj.forEach(element => {
cloneObj.push(element)
});
break;
case '[Object Object]':
Object.keys(obj).forEach(item => {
cloneObj[item] = deepCopy(obj[item], map)
})
break;
default:
cloneObj = obj
break;
}
map.set(obj, cloneObj)
return cloneObj
}
const objs = { name: 'John', age: 18 }
objs.self = objs // 对象自身引用
const arr = [1, 2, 3]
arr[3] = arr // 数组自身引用
console.log(
deepCopy({ name: 1 }), '\n',
deepCopy([1, 2, 3]), '\n',
deepCopy({ name: 'John', age: 18, arr: [1, 2, 3] }), '\n',
deepCopy({ name: 'John', age: 18, birth: new Date('2000-01-01'), reg: /test/i, set: new Set([1, 2, 3]), map: new Map([[1, 'a'], [2, 'b'], [3, 'c']]) }), '\n',
deepCopy(objs), '\n',
deepCopy(arr), '\n',
deepCopy({ name: 'John', age: 18, sayHello: function () { console.log('hello') } }), '\n',
);