幾個例子理解淺拷貝和深拷貝
一、記憶體的堆疊
-
基本型別
存放在棧記憶體中的簡單資料段,資料大小確定,記憶體空間大小可以分配,當它賦給另一個變數的時候,另一個變數發生改變,原資料不會發生改變:
var a = 5; var b = a; b += 1; console.log(b)//6 console.log(a)//5
5種基本資料型別有Undefined、Null、Boolean、Number 和 String,它們是直接按值存放的,所以可以直接訪問。
-
引用型別
存放在堆記憶體中的物件,變數實際儲存的是一個指標,這個指標指向另一個位置。每個空間大小不一樣,要根據情況進行特定的分配。當我們需要訪問引用型別(如物件,陣列,函式等)的值時,首先從棧中獲得該物件的地址指標,然後再從堆記憶體中取得所需的資料。
var a = { userName : 'undefined' }; var b = a; b.userName = 'xiaoming'; console.log(a);//{userName: "xiaoming"} console.log(b);//{userName: "xiaoming"}
上面的例子把a的值賦值給b,當b的值發生改變的時候,a的值也會跟隨改變,像上面的圖解一樣,a和b都是指向同一個地址。如果要讓b得到一個獨立的地址呢?這就涉及到拷貝了。
二、Object.assign
淺拷貝是複製淺層的引用型別,比如複製a = { userName : 'undefined' }這樣的物件就是屬於淺拷貝,它只有一層,像複製b = { info : { userName : 'undefined' } }這樣有巢狀的物件,多層的引用型別,就需要用到深拷貝了。
- Object.assign()方法可以得到一份淺拷貝的引用型別
var a = { userName : 'undefined' }; var b = Object.assign({} , a); b.userName = 'xiaoming'; console.log(a);//{userName: "undefined"} console.log(b);//{userName: "xiaoming"}
這樣,我們就能得到一份淺拷貝內容了,即使是b發生改變,也不會影響到a,它們完全是兩個獨立的個體,但是此方法不適用深拷貝。
三、展開運算子
- 利用展開運算子方法也可以得到一份淺拷貝的引用型別:
var a = { userName : 'undefined' }; var b = {...a}; b.userName = 'xiaoming'; console.log(a);//{userName: "undefined"} console.log(b);//{userName: "xiaoming"}
這樣,我們也能得到一份淺拷貝內容。
四、JSON.parse()&JSON.stringify()
- 利用JSON下面的parse()方法和stringify()方法可以得到一份深拷貝內容,但是這種方法僅適用於物件,stringify()方法可以把物件轉變成json格式的字串,再通過parse()方法進行轉譯成物件來獲得一份拷貝的物件(當然淺拷貝也是適用的):
var a = { info:{userName : 'undefined'}}; var b = JSON.parse(JSON.stringify(a)); b.info.userName = 'xiaoming'; console.log(a);// { info:{userName : 'undefined'}}; console.log(b);// { info:{userName : 'xiaoming'}};
五、for...in&遞迴(推薦)
- 這種方法適用於任何引用型別,原理是使用for..in迴圈,配合遞迴函式實現深層拷貝 :
var a = { info:{userName : 'undefined'}}; var b = copy(a); b.info.userName = 'xiaoming' function copy(obj){ var result = {}; for(var attr in obj){ if( typeof obj[attr] === 'object' ){ result[attr] = copy(obj[attr]); } else{ result[attr] = obj[attr]; } } return result; } console.log(a);// { info:{userName : 'undefined'}}; console.log(b);//{userName: "xiaoming"}
這樣,就可以得到一份深拷貝內容了,其原理就是層層拷貝,利用遞迴的原理,直到最底層不是物件為止,好啦,本次分享就到這裡了,如果有什麼不正確的地方,請各位不吝賜教,謝謝~