SOURCE

//一行代码
JSON.parse(JSON.stringify(obj));
//存在的问题 不能处理 undefined Symbol function, NaN | Infinity会被序列化为null
//第一版
function deepClone(target) {
    if(typeof target !== 'object') return target;//如果不是对象则直接返回
    const cloneTarget = {};
    for(const key in target) {
        cloneTarget[key] = deepClone(target[key])
    }
    return cloneTarget;
}
//存在的问题 不能处理 null Date RegExp 以及数组
function deepClone(target) {
    if(target === null) return target;//如果是null则直接返回
    if(target instanceof Date) return new Date(target);//处理Date
    if(target instanceof RegExp) return new RegExp(target);//处理RegExp
    if(typeof target !== 'object') return target;//如果不是对象 则直接返回
    const cloneTarget = new target.constructor();//创建空对象或者空数组
    for(const key in target) {
        cloneTarget[key] = deepClone(target[key])
    }
    return cloneTarget;
}
// 实例对象的constructor实际上就是构造函数 所以 {}.constructor = Object || [].constructor == Array
//使用 new target.constructor()可以根据target自动创建空数组或者空对象
//存在的问题 不能处理Symbol键
//处理的方法 可以使用 Reflect.ownKeys() 可以返回对象自身的可遍历属性 包括Symbol定义的属性 
//相当于 Object.getOwnPropetyNames(target).concat(Object.getOwnPropetySymbols(target))
function deepClone(target) {
    if(target === null) return target;//如果是null则直接返回
    if(target instanceof Date) return new Date(target);//处理Date
    if(target instanceof RegExp) return new RegExp(target);//处理RegExp
    if(typeof target !== 'object') return target;//如果不是对象 则直接返回
    const cloneTarget = new target.constructor();//创建空对象或者空数组
    Reflect.ownKeys(target).forEach(key => {
        cloneTarget[key] = deepClone(target[key])
    })
}
//存在的问题 循环引用 因为循环引用会导致进入死循环导致栈溢出
//解决方法 额外开辟一个储存空间 在克隆之前先去储存空间查找是否存在对应的对象 如果存在就直接返回 不存在再去clone
function deepClone(target, hash = {}) {
    if(target === null) return target;//如果是null则直接返回
    if(target instanceof Date) return new Date(target);//处理Date
    if(target instanceof RegExp) return new RegExp(target);//处理RegExp
    if(typeof target !== 'object') return target;//如果不是对象 则直接返回
    if(hasj[target]) return hash[target];//如果存在 直接返回
    const cloneTarget = new target.constructor();
    hash[target] = cloneTarget; //如果储存空间没有就直接将其储存进去
    Reflect.ownKeys(target).forEach(key => {
        cloneTarget[key] = deepClone(target[key], hash)
    })
    return cloneTarget

}
//优化空间 可以使用Map和WeakMap来优化 配合垃圾回收机制防止内存泄漏
function deepClone(target, hash = new WeakMap()) {
    if(target === null) return target;//如果是null则直接返回
    if(target instanceof Date) return new Date(target);//处理Date
    if(target instanceof RegExp) return new RegExp(target);//处理RegExp
    if(target instanceof HTMLElement) return target;//处理DOM元素 如果是DOM 没有拷贝的意义
    if(typeof target !== 'object') return target;//如果不是对象 则直接返回
    if(hash.get(target)) return hash.get(target); //如果有直接返回
    const cloneTarget = new target.constructor();
    hash.set(target, cloneTarget);//储存进去
    Reflect.ownKeys(target).forEach(key => {
    cloneTarget[key] = deepClone(target[key], hash) // 递归拷贝每一层
  })
  return cloneTarget     
}
//原文连接: https://juejin.cn/post/7072528644739956773#heading-0
//克隆一个对象 包括它的继承的属性
//1.使用 __proto__
// const obj = {};
// const cloneObj = {
//     __proto__: Object.getPrototypeOf(obj),
//     ...obj
// };
//方法2 兼容性好 使用create
const obj = {};
const cloneObj = Object.assign({}, Object.create(Object.getPrototypeOf(obj)), obj)
console 命令行工具 X clear

                    
>
console