谈谈JavaScript深浅拷贝

浅拷贝

 1 function shallowCopy(source){ 
 2 
 3      var newObj = {};
 4 
 5      for(var attr in source){
 6      newObj[attr] = source[attr];
 7      }
 8 
 9      return newObj;
10 
11      }

一般简单的对象用浅拷贝就行了,深拷贝是对付哪种对象中还有对象的类型。

深拷贝

 1 function deepCopy(source){  
 2         var newObj = {};
 3 
 4         if(typeof source != 'object'){
 5             //console.trace();
 6             return source;
 7         }
 8 
 9         for(var attr in source){
10 
11             newObj[attr] = deepCopy(source[attr]);
12         }
13         //console.trace();
14         //console.log(newObj);
15         return newObj;
16 
17 
18     }
19     var obj1 = {
20         a : { b : 10 }
21     };
22     var obj2 = deepCopy(obj1);//第一层循环为  obj2=deepCopy(obj1)----->newObj[a]=deepCopy(obj1[a])=deepCopy({b:10})------->newObj[a]=
23                               //第二层循环为  newObj[b]=deepCopy({b:10}[b])=deepCopy(10)=10------->newObj[b]=10------->return newObj={b:10}
24                               //newObj[a]={b:10}------>return newObj=a:{b:10}
25 
26     // obj2.a.b = 20;
27     alert(obj2.a.b);     //10
28     alert(obj1.a.b);  //10
29     console.log(obj1,obj2)

主要是用了递归的思想:

obj2=deepCopy(obj1)----->调用deepCopy函数,传入的参数是obj1.第一个if判断是否是对象,如果是则执行下面的for/in循环,如果不是则返回obj。第一个obj1显然是对象,所以执行for/in循环。得到的结果是:

  1. newObj[a]=deepCopy(obj1[a])=deepCopy({b:10})----->再次调用deepCopy函数,传入的参数是对象{b:10},执行for/in循环。得到的结果是:
  2. newObj[b]=deepCopy({b:10}[b])=deepCopy(10)-------->再调用deepCopy函数,传入的参数是{10},不是对象,返回obj,也就是10,得到的结果是:
  3. newObj[b]=deepCopy({b:10}[b])=deepCopy(10)=10.

至此,整个“递”的过程就完成了。下面是“归”的过程。也就是一个相反的过程

  1. deepCopy(10)=10.  代入上面的第二步,执行for/in循环得到newObj[b]=10,然后return newObj={b:10}
  2. 代入上面的第一步,执行for/in循环得到newObj[a]=deepCopy(obj1[a])=deepCopy({b:10})   deepCopy函数执行返回就是第一步的return newObj={b:10},所以newObj[a]={b:10},return newObj={a:{b:10}}

在return newObj;上添加console.log(newObj);输出结果如下:

可以看到的确是return了两次。第一次为{b:10},第二次为{a:{b:10}}.

 

另一种实现是使用parse和stringify:

 1 var a = {
 2     name : { age : 100 }
 3 };
 4 
 5 var str = JSON.stringify(a);
 6 
 7 var b = JSON.parse(str);
 8 
 9 b.name.age = 200;
10 
11 alert( a.name.age ); //100

它能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。

 

我们经常会遇到 手上有数组对象A  要拷贝一个数组对象B,同时修改B不会改变A中元素的值的需求

let o1 = [{name:1,value:1},{name:2,value:2}];
let o2 = JSON.parse(JSON.stringify(o1));
//随便怎么改o2都不会对o1产生任何影响
let o3 = o2.map(item=>{
   delete item.name
   return {
        ...item,
        sex:item.value * item.value
    } 
})

还可以获得新数组对象o3

 数组的话就很简单了  有slice 和 concat方法

let a1 = [1,2,3]
let a2 = a1.concat()
let a3 = a1.slice()
a2[0] = 2
a3[0] = 3
console.log(a1)
console.log(a2)
console.log(a3)
// a1 [1,2,3]
// a2 [2,2,3]
// a3 [3,2,3]

 

posted @ 2019-03-18 13:58  一路向北√  阅读(258)  评论(0编辑  收藏  举报

web应用开发&研究 -

业精于勤而荒于嬉。

工作,使我快乐。


Font Awesome | Respond.js | Bootstrap中文网