深拷贝 浅拷贝
搞清楚深拷贝浅拷贝之前,首先要知道基本数据类型和引用数据类型
数据类型:
1.基本数据类型
key和value都会存储到栈内存中
2.引用数据类型
key存在栈内存中,value存在堆内存中,栈会提供一个value的引用地址指向堆内存
实现浅拷贝的方法
1.for in 只循环第一层 (第二层就是copy的引用)
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) // 3View Code
3.直接赋值法
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.采用递归去拷贝所有层级的属性
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对象来实现深拷贝
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 ,扩展运算符... ,(仅对数组或者对象中的值是基本数据类型是是深拷贝)
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