6、javascript中物件和陣列的深拷貝
不管是在面試中還是我們的專案中經常會用到陣列或者物件的深拷貝,下面我就自己總結的分享給大家。
首先要知道什麼是深拷貝?什麼是淺拷貝?
深拷貝:源物件與拷貝物件互相獨立,其中任何一個物件的改動都不會對另外一個物件造成影響。
淺拷貝:拷貝出來的目標物件的指標和源物件的指標指向的記憶體空間是同一塊空間。
怎麼理解呢?
舉個栗子:定義了一個物件 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; 3a.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相互獨自,互不影響。