# 深拷贝
模拟实现一个深拷贝,并考虑对象相互引用以及 Symbol 拷贝的情况
利用一个WeakMap来破解相互引用
利用Object.getOwnPropertySymbols
来获取Symbol键值
function deepClone(target, hash = new WeakMap()) {
// 已经遍历过了就返回
if (hash.has(target)) return target
let cobj
// 处理为null的特殊情况
if (target === null) {
return target
}
// 如果是基本数据类型 则直接返回了
const t = typeof target
switch (t) {
case 'string':
case 'number':
case 'boolean':
case 'undefined':
case 'symbol':
return target
}
if (Array.isArray(target)) {
hash.set(target, true);
cobj = []
target.forEach((o) => {
cobj.push(deepClone(o, hash))
})
} else {
cobj = {}
if (Object.prototype.toString.call(target) === '[object Object]') {
hash.set(target, true)
// 同时考虑string key 和 symbol key
const keys = [...Object.getOwnPropertyNames(target), ...Object.getOwnPropertySymbols(target)]
for (let i = 0, len = keys.length; i < len; i++) {
const key = keys[i]
cobj[key] = deepClone(target[key], hash)
}
} else {
// 考虑到可能是函数等的情况
cobj = target
}
}
return cobj
}
const source = {
a: 1,
b: 'string',
c: Symbol('foo'),
d: undefined,
e: null,
f: function () {},
h: new Date(),
arr: [{ d: 'd' }, 22, 44],
obj: {
x: 1
}
}
source.mySelf = source
let symbol2 = Symbol('bar')
source[symbol2] = 'xdyuan'
const ret = deepClone(source)