JS 深拷贝(全)

1. 使用JSON中的方法
JSON.parse(JSON.stringify(target)) // target为要拷贝的对象

let obj1 = {
    name:'xiaoming',
    info:{
        address: 'beijing'
    }
}
let obj2 = JSON.parse(JSON.stringify(obj1))

2.使用递归进行深拷贝

function deepClone(obj) {
    if (typeof obj === 'object' && target !== null) {
        let cloneObj = Array.isArray(obj) ? [] : {}
        for (let key in obj) { //遍历
            if (typeof obj[key] === 'object') {
                cloneObj[key] = deepClone(obj[key]) //是对象就再次调用该函数递归
            } else {
                cloneObj[key] = obj[key] //基本类型的话直接复制值
            }
        }
        return cloneObj
    } else {
        return target;
    }
}

上边两种已经可以满足大部分应用场景,但是对于Symbol类型的数据和不可枚举属性以及RegExp、Date、Error、Function等引用类型无法进行拷贝。

3.改进版深拷贝

// 判断数据是否为一个引用类型对象,并且不为null
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)

const deepClone = function(obj, hash = new WeakMap()) {

    if (obj.constructor === Date)
    
        return new Date(obj) // 日期对象直接返回一个新的日期对象

    if (obj.constructor === RegExp)

        return new RegExp(obj) //正则对象直接返回一个新的正则对象

    //如果循环引用了就用 weakMap 来解决,weakMap为弱引用,会自动进行垃圾回收~~~~
    if (hash.has(obj)) return hash.get(obj)

    // 遍历所有键的特征,Object.getOwnPropertyDescriptors(obj)返回的是一个对象,对象的属性名就是源对象的属性名,属性值就是该对象的描述对象(即访问器属性或数据属性)
    let allDesc = Object.getOwnPropertyDescriptors(obj)
    
    //遍历传入参数所有键的特性
    // 详见  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors#%E6%B5%85%E6%8B%B7%E8%B4%9D%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1
    let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)

    //继承原型链,这样下方进行遍历赋值的时候,也会将原型链中的数据也进行拷贝
    hash.set(obj, cloneObj)
    
    // Reflect.owmKeys(obj)方法类似于 Object.keys(obj), 但是后者会受enumerable影响,前者不会,使用这个方法可以将Symbol类型的数据也进行拷贝。
    // 详见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
    for (let key of Reflect.ownKeys(obj)) {
        cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
    }
    return cloneObj
}

你可能感兴趣的:(JS 深拷贝(全))