深度拷贝(克隆)与浅度拷贝(克隆)区别,及原生js深克隆的封装

之前对深拷贝,浅拷贝一直很头疼,一看到这些字眼,就揪心。于是就不断地查资料,查资料,查资料。。。好在现在算是搞清楚了。写在这希望能帮助到和我有同样疑惑的人们,同样也以防以后自己又给忘掉再次揪心,,,哈哈哈,好了皮一下,言归正传。对于浅拷贝,深拷贝,他俩的最大区别 请看斜体字部分,下面就一一了解。

    一. 什么是拷贝?

       答:拷贝就是我们常说的复制或者克隆一个对象。其中拷贝分为浅拷贝和深拷贝。

     二..什末是浅拷贝?

      答:浅拷贝就是对内存地址的拷贝,使得‘拷贝出来’的和‘原来的’指向的是同一内存地址,它对于对象只是简单的引用而已,只能拷贝一层,不能对子对象进行拷贝。导致拷贝完后前后两个对象相互影响,就是你变我也变,这样在实际开发过程中很不好。如果还没理解,那就看看下面的例子:

1.普通对象

     var obj={
     		name:'du',
     		age:21,
     		borther:{
     		    name:'rui',
     		    age:12
     		}
     	};
        var obj1 = obj;
        obj1.sex='女';
        console.log(obj1,obj);

        //打印出结果为:
        obj1:{name: "du", age: 21, borther: {…}, sex: "女"}

        obj:{name: "du", age: 21, borther: {…}, sex: "女"}

由此看出在obj1发生改变时,obj也发生了相应的改变。这样就局限了好多。。。。

2.数组对象

         var arr=[1,2,3,{a:6}];
         var arr1=arr.concat();
         arr1[3].b=7;
         arr[3].c=8;
         console.log(arr,arr1);
//打印出结果为
 arr:  [1, 2, 3, {…}]0: 11: 22: 33: {a: 6, b: 7, c: 8}length: 4__proto__: Array(0)
 arr1: [1, 2, 3, {…}]0: 11: 22: 33: {a: 6, b: 7, c: 8}length: 4__proto__: Array(0)

由此看出在数组里面也是如此。。。。。这就是浅拷贝。

三.什末是深拷贝?

答:深拷贝就是对对象中的子对象进行递归拷贝,复制,拷贝后两个对象相互不受影响。因为他们会有不同的地址,会在堆中有不同的内存,简短话总结 就是拥有相同的值,不同的地址。下面写个例子,就拿JSON.parse()/JSON.stringify()会更清楚。

  var obj={
     		name:'du',
     		age:21,
     		borther:{
     		    name:'rui',
     		    age:12
     		}
     	};
   //JSON.stringify()是将json对象转换为字符串型,JSON.parse()是将字符串转换为json对象
     	var obj1=JSON.parse(JSON.stringify(obj));
        obj1.sex='女';
        obj.borther.sex='男';
        console.log(obj1,obj);

  //打印出来结果为
  obj1:{name: "du", age: 21, borther: {…}, sex: "女"} //注意对象的属性
        borther:{name: "rui", age: 12}               //注意子对象borther的结果


  obj: {name: "du", age: 21, borther: {…}}          //注意对象的属性
        borther:{name: "rui", age: 12, sex: "男"}   //注意子对象borther的结果

由此看出在obj1发生改变时,obj并没有改变,obj发生改变时,obj1并没有改变,这就是深拷贝。

四. 深克隆的封装

那末看了这些肯定都懂了什末是浅拷贝,深拷贝和他们之间的区别了。但是不足一点就是在深拷贝中只看到了json数据用法,那末能不能封装一个深拷贝的方法呢,还真有,哈哈哈哈哈哈,且看下面

在实现深度拷贝时,你得先在脑子中构建出一个思路框架出来,就是怎末弄,为什末这样弄。。。

1.先得遍历对象,这是毋庸置疑的

2.判断是不是原始值   typeof()  -->object

3.判断是数组还是对象  (方法有instanceof  /  toString  /  constructor)

4.建立相应的数组或对象

5.递归

有了这些思路后,写起代码就容易多了

function deepClone(origin ,target){
          var target = target||{};              //以防用户没传,默认是对象
          for(var prop in origin){
             //hasOwnProperty是用来判断某个属性是不是在对象自己的属性,它不会检测到原型链上去
             if(origin[prop]!==null&&origin.hasOwnProperty(prop)){   //一定得确定对象上的属性不是原型链上的
                if(typeof(origin[prop])=='object'){    //判断是不是原始值
                  	   //在不是原始值的情况下,判断是数组还是对象
	           target[prop] = Object.prototype.toString.call(origin[prop])=='[object Array]'?[]:{};
	           deepClone(origin[prop],target[prop]);

                  }else{
                        target[prop]=origin[prop];
                  }
             }

          }
           return target;
      }
 var obj={
     		name:'du',
     		age:21,
     		borther:{
     		    name:'rui',
     		    age:12
     		}
     	};
var obj1=deepClone(obj,obj1);
        obj1.sex='女';
        obj.borther.sex='男';
        console.log(obj1,obj);
//打印结果为
obj1:   {name: "du", age: 21, borther: {…}, sex: "女"}  
        其中borther: {name: "rui", age: 12}
obj:    {name: "du", age: 21, borther: {…}}             
        其中borther: {name: "rui", age: 12, sex: "男"}

由此看出,互不影响。一个深拷贝就封装完成了。

猜你喜欢

转载自blog.csdn.net/du111_/article/details/86651331