不管是在面试中还是我们的项目中经常会用到数组或者对象的深拷贝,下面我就自己总结的分享给大家。
首先要知道什么是深拷贝?什么是浅拷贝?
深拷贝:源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。
浅拷贝:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间。
怎么理解呢?
举个栗子:定义了一个对象 A={x:0,y:0},和一个对象B,我现在要将对象A赋值给对象B,如果对象A的值发生改变后对象B的值也发生改变的话我们称这种拷贝为浅拷贝,如果A的值发生变化后B的值不发生变化则称这种拷贝为深拷贝。当A被赋值时就已经有了自己的内存,深拷贝的同时为对象B开辟了 一个新的内存,A所对应的内存和B所对应的内存相互独自,互不影响。而浅拷贝时不会为B开辟新的内存,B指向了A的内存,A的值的变化会影响B的值。
1、对象(object)的深拷贝和浅拷贝:
1.1对象的浅拷贝:
1 var a={x:0,y:0}; 2 var b=a; 3 a.x=2; 4 console.log(a); //=>Object {x: 2, y: 0} 5 console.log(b); //=>Object {x: 2, y: 0}
以上代码很简单,定义了一个对象a,将对象a赋值给对象b,修改a的x值为2,打印a和b的值,结果显示a的x值为2,而b的x值也为2,这就是简单的浅拷贝。
1.2对象的深拷贝的几种方法:
方法1:利用JSON.parse();
var obj1={x:0,y:0}; var obj2=JSON.parse(JSON.stringify(obj1)); obj1.x=2; console.log(obj1); //=>Object {x: 2, y: 0} console.log(obj2); //=>Object {x: 0, y: 0}
方法2:es6中的Object.assign();
var obj1={x:1,y:1}; var obj2=Object.assign({},obj1); obj1.x=2; console.log(obj1);//=>Object {x: 2, y: 1} console.log(obj2);//=>Object {x: 1, y: 1}
以上两种方法显示:obj1的值发生变化不会影响obj2的值。
2、数组(Array)的深拷贝和浅拷贝:
2.1数组的浅拷贝:
var arr1=[1,2,3]; var arr2=arr1; arr1.push(5); console.log(arr1);//=>[1, 2, 3, 5] console.log(arr2);//=>[1, 2, 3, 5]
以上通过赋值的方法进行浅拷贝,结果显示,数组arr1发生变化时数组arr2的值也发生变化。
2.2数组深拷贝的几种方法:
方法一:利用slice()方法:
var arr=[1,2,3]; var arr2=arr.slice(); arr.push(4); console.log(arr); //=>[1, 2, 3, 4] console.log(arr2);//=>[1, 2, 3]
方法二:利用 Object.assign() 方法:
var arr=[1,2,3]; var arr2=Object.assign([],arr); arr.push(4); console.log(arr);//=>[1, 2, 3, 4] console.log(arr2);//=>[1, 2, 3]
方法三:数组的 concat() 方法:
var arr=[1,2,3]; var arr2=arr.concat(); arr.push(4); console.log(arr);//=>[1, 2, 3, 4] console.log(arr2);//=>[1, 2, 3]
方法四:es6中的扩展运算符:
let arr=[1,2,3]; let [...arr2]=arr; arr.push(4); console.log(arr);//=>[1, 2, 3, 4] console.log(arr2);//=>[1, 2, 3]
方法五:通过遍历将值赋值:
let arr=[1,2,3]; let arr2=arr.map((item,index)=>{ return item; }) arr.push(4); console.log(arr);//=>[1, 2, 3, 4] console.log(arr2);//=>[1, 2, 3]
通过以上5中方法实现了数组的深拷贝,数组arr1和数组arr2相互独自,互不影响。