SOURCE

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 命令行工具 X clear

                    
>
console