Javascript 手写深拷贝

1.数据类型

  • 基本数据类型:名和值都存储在栈内存中;在复制时,栈内存会新开辟一个内存,用来存储新的变量,这个时候修改原变量的值,不会对新生成的变量产生影响。
  • 引用数据类型:名存在于栈内存中,值存在于堆内存中,栈内存的会提供一个引用地址指向堆内存中的值。当对引用类型a进行拷贝时(b = a),其实复制的是a的引用地址,而非堆里面的值。当对a里面的数据进行修改时,由于a和b指向的是同一个地址,b自然就受到了影响。这就是所谓的浅拷贝。如果,要是在堆内存中也开辟一个新的内存专门为b存值,就像基本类型那样,就可以达到深拷贝的效果了。

2.实现深拷贝的方法

  • 通过递归去复制引用类型的所有层级属性(这里的一些对象如Error、RegExp、Date等都会变成{})
const deepClone = (obj = {}) => {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }
    const objClone = Array.isArray(obj) ? [] : {};
    if (typeof obj === 'object') {
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                // 判断ojb子元素是否为对象,如果是,递归复制
                if (obj[key] && typeof obj[key] === 'object') {
                    objClone[key] = deepClone(obj[key]);
                } else {
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
} 
  • 使用JSON对象的parse和stringify方法实现
function deepClone(obj) {
    let _obj = JSON.stringify(obj);
        objClone = JSON.parse(_obj);
    return objClone
}

这个方法有以下弊端:

  • 时间对象(对象=>字符串);
  • RegExp、Error对象(对象=>空对象);
  • 函数、undefined(丢失);
  • NaN、Infinity和-Infinity(=> null);
  • 会丢弃constructor

注意:Object.assign是浅拷贝!!!

 

猜你喜欢

转载自blog.csdn.net/josavion/article/details/114634667