likes
comments
collection
share

手写一个简单的深拷贝

作者站长头像
站长
· 阅读数 26

什么是深拷贝?

了解深拷贝之前需要对浅拷贝有个基本理解。

浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

相对应的深拷贝就是:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

深拷贝的作用

简而言之,深拷贝的作用是创建一个新的对象或数组,从而保留原始对象或数组的值,同时不与原始对象共享内存,这样原始对象的改变不会影响新的对象。常用于对象A的属性中包含了另一个对象a,为了避免内部的对象a被拷贝之后还会被新对象B修改的情况。

常规深拷贝的弊端

常规深拷贝都是用JSON.stringify()和JSON.parse()进行深拷贝。但是这个方法有几个弊端,JSON.stringify()和JSON.parse()会忽略undefined、Symbol和函数等特殊值,导致无法拷贝。并且如果尝试拷贝bigInt类型的值或者是循环引用的数据,会直接报错。

//尝试深拷贝bigInt类型 
let obj={ 
    a:123n 
} 
let newObj = JSON.parse(JSON.stringify(obj)) 
console.log(newObj); //此处会报错

手写深拷贝

先来手写一个简单的深拷贝:

function deepClone(target) {
    if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {};
        for (const key in target) {
            cloneTarget[key] = deepClone(target[key]);
        }
        return cloneTarget;
    } else {
        return target;
    }
};

这个深拷贝添加了对数组的支持,但是不支持循环引用的对象。

手写一个简单的深拷贝

为了解决这个问题,我们需要借助Map对象

function deepClone(target, map = new Map()) {
    if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {};
        if (map.get(target)) {
            return map.get(target);
        }
        map.set(target, cloneTarget);
        for (const key in target) {
            cloneTarget[key] = deepClone(target[key], map);
        }
        return cloneTarget;
    } else {
        return target;
    }
};

可以看到成功拷贝,并且内部的对象变成了Circular类型

手写一个简单的深拷贝

接下来可以用WeakMap类型替换Map类型,避免对循环引用的对象进行内存释放,但是内部的对象却没被释放的情况

function deepClone(target, map = new WeakMap()) {
    if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {};
        if (map.get(target)) {
            return map.get(target);
        }
        map.set(target, cloneTarget);
        for (const key in target) {
            cloneTarget[key] = deepClone(target[key], map);
        }
        return cloneTarget;
    } else {
        return target;
    }
};
转载自:https://juejin.cn/post/7367676494976319498
评论
请登录