JS - 进行深拷贝的两种方法

概念:

在js程序中出现两种拷贝 浅拷贝 和 深拷贝;

  • 浅拷贝只是拷贝了栈空间的地址 不会拷贝堆空间的内存;当一个对象发生改变的时候 另一个对象也会受到影响;
  • 深拷贝是要拷贝栈空间的地址和堆空间的内存; 所以说深拷贝之后 两个对象之间没有什么关系 ,不会受任何一方影响;

1,序列化和反序列化进行深拷贝:

		错误的拷贝方法(直接赋值)  ==============反向案例======================
        let obj5 = {name : 'Eric',age : 18,sex : '男'};
        let obj6 = obj5 ;
        obj6.name = 'xinjie';
        console.log("obj6:",obj6);
        console.log("obj5 :",obj5);
        // 会发现把原数组都改变了
        obj6: { name: 'xinjie', age: 18, sex: '男' }
        obj5 : { name: 'xinjie', age: 18, sex: '男' }
        
        
        正确的使用方法======================序列化和反序列化==================
        let obj5 = {name : 'Eric',age : 18,sex : '男'};
         
        先序列化将对象转化为json字符串 这时对象就和下面的没有任何关系了
        因为字符串是标量类型  所以说只存储在栈空间 和堆空间的对象没有任何关系
        let json6=JSON.stringify(obj5);
        // 再将JSON转化会对象
        let newObj5=JSON.parse(json6);
        // 进行改变姓名
        newObj5.name = 'xinjie'
        console.log("原来的对象",obj5,);
        console.log("深拷贝过的对象:",newObj5);
        console.log(Object.is(obj5 ,newObj5)) = false 事实证明两个对象并不相等
       

通过JSON.stringify实现深拷贝有几点要注意:

  • 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
  • 无法拷贝不可枚举的属性,无法拷贝对象的原型链上的属性
  • 拷贝Date引用类型会变成字符串
  • 拷贝RegExp引用类型会变成空对象
  • 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
  • 无法拷贝对象的循环应用(即obj[key] = obj)

2,自定义函数进行深浅拷贝

上面序列化这种深拷贝方式由于出现种种问题,最好还是我们进行封装一个可以深拷贝多层的函数,代码如下:


let arr = ['华佗','李时珍','张仲景',['白起','王翦'],'扁鹊','喜来乐'];
// 自定义函数进行深浅拷贝 
function deepCopy(object){
    let result;
    if (Object.prototype.toString.call(object) == '[object Object]'){
        result = {};
    }else if (Object.prototype.toString.call(object) == '[object Array]'){
        result = [];
    }else{
        return '不符合深拷贝的数据类型';
    }
    // 遍历空对象或者是空数组  也就是要拷贝的对象
    for(let key in object){
        if (typeof object[key] == 'object'){
            result[key] = deepCopy(object[key]);
        }else{
            result[key] = object[key];
        }
    }
    return result;
}
console.log(deepCopy(arr));  //[object Array]
结果如下:
[ '华佗', '李时珍', '张仲景', [ '白起', '王翦' ], '扁鹊', '喜来乐' ]

3,还可以通过Object.assign()方法和展开运算符进行深拷贝,但也不能面对多层嵌套这种情况;它们只能深拷贝一层;

.......

你可能感兴趣的:(javascript,前端,开发语言)