实现一个详细的深拷贝

91 阅读1分钟

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',
);