// Determine whether the data type is complex
const isComplexDataType = obj= > (typeof obj === 'object' || typeof obj === 'function') && (obj ! = =null)
// Use WeekMap() to refer to its own keys as weak references. If there are no other references to the same object, the object will be garbage collected
// To solve the problem of circular reference, set up a hash table to store the copied object for cyclic detection, when the detection of the current object exists in the hash table, fetch the value and return
const deepClone = function (obj, hash = new WeakMap(a)) {
// Check the hash table to prevent cyclic copying. Obj =>obj.loop= original obj if looped (object loop reference), the first obj will be found in weekMap
if (hash.has(obj)) return hash.get(obj)
// If the parameter is a reference type such as Date, RegExp, Set, Map, WeakMap, WeakSet, etc., a new instance will be generated directly
let type = [Date.RegExp.Set.Map.WeakMap.WeakSet]
if (type.includes(obj.constructor)) return new obj.constructor(obj)
// Iterate over all attribute descriptors for the passed argument
let allDesc = Object.getOwnPropertyDescriptor(obj)
// Inherit the prototype
let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
// Get all Symbol type keys
let symKeys = Object.getOwnPropertySymbols(obj)
// Copy the property corresponding to the Symbol key
if (symKeys.length > 0) {
symKeys.forEach(x= > {
cloneObj[x] = isComplexDataType(obj[x]) ? deepClone(obj[x], hash) : obj[x]
})
}
// Hash table set values
hash.set(obj, cloneObj)
// reflect.ownkeys (obj) copies non-enumerable property and symbol types
for (let key of Reflect.ownKeys(obj)) {
// deepClone is recursively called if the value is a reference type and not a function
cloneObj[key] = (isComplexDataType(obj[key]) && typeofobj[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('-- -- -- -- -- -- -- -- -- -- -- -- --');
// Handle cyclic reference tests
let a = {
name: 'lsz'.course: {
vue: 'vue.js'.react: 'react.js'
},
a1: undefined.a2: null.a3: 123.a4: NaN
}
// Object loop reference
a.circleRef = a
let b = deepClone(a)
console.log('[ b ] >', b)
Copy the code
[ 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]
}
Copy the code