优雅的实现深拷贝

273 阅读1分钟
把基本需要的定义在函数外面,防止递归的时候过多的不必要运行
// 获取类型,把多余的删掉

const getType = (obj) => Object.prototype.toString.call(obj).replaceAll( new RegExp(/\[|\]|object /,'g'), '')

// 记录引用类型

const arrList = ['Date', 'RegExp', 'Map', 'WeakMap', 'Set', 'WeakSet', 'Error']



function deepClone(obj) {

    let res = null

    const type = getType(obj)
    if (type === 'Object' && obj !== null) {

        res = {}
        //使用Reflect.ownKeys() 可以遍历自身所以可以枚举的属性(包括symbol)
        for (const key of Reflect.ownKeys(obj)) {

            if (Object.hasOwnProperty.call(obj, key)) {

                res[key] = deepClone(obj[key])
            }

        }

    } else if (Array.isArray(obj)) {

        res = []

        obj.forEach((item,i) => {

            res[i] = deepClone(item)

        })

    } else if (arrList.includes(type)) {

        res = new obj.constructor(obj)    

    } else {

        res = obj

    }

    return res

}
测试数据
const map1 = new Map()

map1.set('key1', 'value1')

map1.set('key2', 'value2')

const a = [12,2]

let str = '123'

let symbol = Symbol('12135')

const target = {

    field1: 1,

    field2: undefined,

    field3: {

        child: "child",

    },

    field4: [2, 4, 8],

    empty: null,

    bool: new Boolean(true),

    num: new Number(2),

    str: new String(2),

    symbol: Object(Symbol(1)),

    [symbol]:'4543',

    date: new Date(),

    reg: /\d+/,

    error: new Error(),

    func1: () => {

        let t = 0;

        console.log("coder", t++);

    },

    func2: function (a, b) {

        return a + b;

    },

};


const test1 = deepclone(map1)

const test2 = deepclone(a)

const test3 = deepclone(str)

const test4 = deepclone(target)

str = '456'

a.push(45)

map1.set('key3', 'value3')


console.log('test1',test1)

console.log('map1',map1)


console.log('test2',test2)

console.log('a',a)


console.log('test3',test3)

console.log('str',str)



console.log('test4',test4)

console.log('target',target)