把基本需要的定义在函数外面,防止递归的时候过多的不必要运行
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 = {}
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)