deep clone 需要考虑引用类型(object, function),primitve 类型和数组,Map, Set,如果obj是一个object,那么需要copy它的每一个属性。如果obj是一个数组,那么需要拷贝它的每一个数组元素,如果是Map需要新建一个Map,如果是Set需要新建一个Set。因此需要Object.keys(), Object.entries(),Array.prototype.map, Map.prototype.set, Set.prototype.add 等方法。
function getType(obj) {
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()
}
function deepClone(obj) {
let target
if (null === obj) {
return null
}
const type = getType(obj)
if (type === 'map') {
target = new Map()
for (let [key, value] of obj) {
target.set(key, value)
}
} else if (type === 'set') {
target = new Set()
for (let item of obj) {
target.add(item)
}
} else if (type === 'array') {
target = obj.map(item => {
return deepClone(item)
})
} else {
target = {}
Object.entries(obj).forEach(([key, value]) => {
target[key] = typeof value === 'object' ? deepClone(value) : value
})
}
return target
}
const a1 = Symbol('foo')
const a2 = new Set([1, 2, 3])
const a3 = new Map([[1, 'one'], [2, 'two']])
const a = [{ foo: a2, foo2: a3, foo3: a1, obj: { a: 1, b: 2 }, c: [{d: 4}] }];
const b = deepClone(a);
console.log('b', b[0].foo, b[0].foo2, b[0].foo3)