一、內存的堆棧
- 基本類型
存放在棧內存中的簡單數據段,數據大小確定,內存空間大小可以分配,當它賦給另一個變量的時候,另一個變量發生改變,原數據不會發生改變:
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"}
這樣,就可以得到一份深拷貝內容了,其原理就是層層拷貝,利用遞歸的原理,直到最底層不是對象為止,好啦,本次分享就到這里了,如果有什么不正確的地方,請各位不吝賜教,謝謝~