JS深拷贝与浅拷贝

深拷贝  浅拷贝

搞清楚深拷贝浅拷贝之前,首先要知道基本数据类型和引用数据类型

数据类型:

1.基本数据类型

    key和value都会存储到栈内存中

2.引用数据类型

    key存在栈内存中,value存在堆内存中,栈会提供一个value的引用地址指向堆内存

JS深拷贝与浅拷贝

实现浅拷贝的方法

1.for in 只循环第一层 (第二层就是copy的引用)

JS深拷贝与浅拷贝
 1 // 只复制第一层的浅拷贝
 2 function simpleCopy(obj1) {
 3     var obj2 = Array.isArray(obj1) ? [] : {};
 4     for (let i in obj1) {
 5         obj2[i] = obj1[i];
 6     }
 7     return obj2;
 8 }
 9 var obj1 = {
10        a: 1,
11        b: 2,
12        c: {
13              d: 3
14           }
15     }
16 var obj2 = simpleCopy(obj1);
17 obj2.a = 3;
18 obj2.c.d = 4;
19 alert(obj1.a); // 1
20 alert(obj2.a); // 3
21 alert(obj1.c.d); // 4
22 alert(obj2.c.d); // 4 
23  
24 
25 var obj = {
26     a: 1,
27     b: 2
28 }
29 var obj1 = Object.assign(obj);
30 obj1.a = 3;
31 console.log(obj.a) // 3 
View Code

 

3.直接赋值法

JS深拷贝与浅拷贝
1 let a=[0,1,2,3,4],
2     b=a;
3 console.log(a===b);
4 a[0]=1;
5 console.log(a,b); 
View Code

 

实现深拷贝的方法

1.采用递归去拷贝所有层级的属性

JS深拷贝与浅拷贝
 1 function deepClone(obj){
 2     let objClone = Array.isArray(obj)?[]:{};
 3     if(obj && typeof obj==="object"){
 4         for(key in obj){
 5             if(obj.hasOwnProperty(key)){
 6                 //判断ojb子元素是否为对象,如果是,递归复制
 7                 if(obj[key]&&typeof obj[key] ==="object"){
 8                     objClone[key] = deepClone(obj[key]);
 9                 }else{
10                     //如果不是,简单复制
11                     objClone[key] = obj[key];
12                 }
13             }
14         }
15     }
16     return objClone;
17 }    
18 let a=[1,2,3,4],
19     b=deepClone(a);
20 a[0]=2;
21 console.log(a,b); 
View Code

 

 2.通过JSON对象来实现深拷贝

JS深拷贝与浅拷贝
1 function deepClone2(obj) {
2   var _obj = JSON.stringify(obj),
3     objClone = JSON.parse(_obj);
4   return objClone;
5 }​
View Code
缺点: 无法实现对对象中方法的深拷贝,会显示为undefined 

3.如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象

var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign({}, obj); // obj赋值给一个空{}
obj1.a = 3;
console.log(obj.a);// 1​ 

 

4.lodash函数库cloneDeep方法实现深拷贝

5.其它情况

/ 当value是基本数据类型,比如String,Number,Boolean时,是可以使用拓展运算符进行深拷贝的
// 当value是引用类型的值,比如Object,Array,引用类型进行深拷贝也只是拷贝了引用地址,所以属于浅拷贝​

 数组的slice  splice  concat ,扩展运算符...  ,(仅对数组或者对象中的值是基本数据类型是是深拷贝)

JS深拷贝与浅拷贝
 1 // 当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝
 2 var arr1 = ["1","2","3"];
 3 var arr2 = arr1.concat();
 4 arr2[1] = "9";
 5 console.log("数组的原始值:" + arr1 );
 6 console.log("数组的新值:" + arr2 );
 7 // 当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝
 8 var arr1 = [{a:1},{b:2},{c:3}];
 9 var arr2 = arr1.concat();
10 arr2[0].a = "9";
11 console.log("数组的原始值:" + arr1[0].a ); // 数组的原始值:9
12 console.log("数组的新值:" + arr2[0].a ); // 数组的新值:9​
13 
14 
15 // 当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝
16 // 当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝
17 var arr1 = ["1","2","3"]; 
18 var arr2 = arr1.slice(0);
19 arr2[1] = "9";
20 console.log("数组的原始值:" + arr1 );
21 console.log("数组的新值:" + arr2 );
View Code

 

上一篇:浅拷贝与深拷贝以及BeanUtils.copyProperties()


下一篇:JVM 内置锁 synchronized 的几种状态概述