function deepClone (source) {
// 引用类型判断
const isObject = target => target !== null && typeof target === 'object'
if (!isObject(source)) return source
const objectTag = '[object Object]',
arrayTag = '[object Array]',
setTag = '[object Set]',
mapTag = '[object Map]'
const deepTags = [objectTag, arrayTag, setTag, mapTag]
// 实际类型判断
const getType = target => Object.prototype.toString.call(target)
// new初始化
const getIns = target => new target.constructor
// 循环引用查询
const find = (item, list) => {
for (let i = 0; i < list.length; i++) {
let val = list[i].source
if (val === item) return list[i].target
}
return null
}
const clone = (source, list = []) => {
if (!isObject(source)) return source
const type = getType(source)
// 创建数据类型实例
let target = getIns(source)
// 判断循环引用判断
const theTar = find(source, list)
if (theTar) return theTar
list.push({source, target})
// symbolKey
const symKeys = Object.getOwnPropertySymbols(source)
if (symKeys.length) {
for (let i = 0; i < symKeys.length; i++) {
let key = symKeys[i]
target[key] = clone(source[key], list)
}
}
// Set
if (type === setTag) {
for (let item of source) {
target.add(clone(item, list))
}
return target
}
// Map
if (type === mapTag) {
for (let [key, item] of source) {
target.set(key, clone(item, list))
}
return target
}
// object/array
for (let key in source) {
if (source.hasOwnProperty(key)) {
target[key] = clone(source[key], list)
}
}
return target
}
return clone(source)
}
console