const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)
const deepClone = function (obj, hash = new WeakMap()) {
if (hash.has(obj)) return hash.get(obj)
let type = [Date, RegExp, Set, Map, WeakMap, WeakSet]
if (type.includes(obj.constructor)) return new obj.constructor(obj)
let allDesc = Object.getOwnPropertyDescriptor(obj)
let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
let symKeys = Object.getOwnPropertySymbols(obj)
if (symKeys.length > 0) {
symKeys.forEach(x => {
cloneObj[x] = isComplexDataType(obj[x]) ? deepClone(obj[x], hash) : obj[x]
})
}
hash.set(obj, cloneObj)
for (let key of Reflect.ownKeys(obj)) {
cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
}
return cloneObj
}
let obj = {
arr: [0, 1, 2, 3, 4, 5, 6]
}
let obj2 = deepClone(obj)
obj2.str = 'flten'
console.log('[ obj2 ] >', obj2)
console.log('-------------');
let a = {
name: 'lsz',
course: {
vue: 'vue.js',
react: 'react.js'
},
a1: undefined,
a2: null,
a3: 123,
a4: NaN
}
a.circleRef = a
let b = deepClone(a)
console.log('[ b ] >', b)
[ obj2 ] > {
arr: Array {
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
length: 7
},
str: 'flten'
}
-------------
[ b ] > {
name: 'lsz',
course: { vue: 'vue.js', react: 'react.js' },
a1: undefined,
a2: null,
a3: 123,
a4: NaN,
circleRef: [Circular]
}