浅拷贝和深拷贝

一、ECMAScript数据类型

1)基本数据类型:简单的数据段(Number、String 、Boolean、Null和Undefined)
2)引用数据类型:多个值构成的对象(Object 、Array 、Function等)

二、变量的复制

1)原始值:将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已(且一个变量的改变不会影响另一个变量)。

2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是在栈内存多了一个指向这个对象指针罢了)

三、深复制和浅复制

浅拷贝: 浅拷贝就是流于表面的拷贝方式;当属性值为对象类型时,只拷贝了对象数据的引用(指针),导致新旧数据没有完全分离,还会互相影响。
深拷贝:深拷贝就是 ‘完全’拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会互相影响

四、如何实现对象、数组的深拷贝

1)方法一

JSON.parse(JSON.stringify(Obj))
注意:这种方式不能深拷贝有属性值为函数的对象

1)方法二

   function deepCopy(target){
       if(typeof target!=='object')return;
           var newObj = target instanceof Array?[]:{};
           for(var item in target){
          //只复制元素自身属性,不复制原型链上的
           if(target.hasOwnProperty(item)){
              newObj[item] = typeof target[item]=='object'?  deepCopy(target[item]):target[item]//是对象就把对象属性拆分出来赋值
            }
        }
        return newObj;
    }
    var test = [1,'a',{name:'lei',age:18}];
    var copy2 = deepCopy(test);
    copy2[2].name = 'zhang';
    console.log(test);// [1,'a',{name:'lei',age:18}];
    console.log(copy2);// [1,'a',{name:'zhang',age:18}];

五、Object.assign()

用来复制一个对象

  Object.assign({}, obj)

注意:Object.assign() 只是一级属性复制,比浅拷贝多深拷贝了一层而已
针对深拷贝,需要使用其他方法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。

//可使用此方法拷贝(一级属性)
 let obj1 = { a: 0 , b: 1};
 let obj2 = Object.assign({}, obj1);  
 obj2.a = 1;
 console.log(JSON.stringify(obj1)); // { a: 0, b:1}
 console.log(JSON.stringify(obj2)); // { a: 1, b:1}
//不可使用此方法拷贝(多级属性)
 let obj1 = { a: 0 , b: { c: 0}};
 let obj2 = Object.assign({}, obj1);  
 obj2.b.c = 3;
 console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
 console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}//都改变了

参考:
https://www.cnblogs.com/cxying93/p/6106469.html
https://blog.csdn.net/u011277123/article/details/78376487

你可能感兴趣的:(浅拷贝和深拷贝)