基本數據類型
在深入探討深拷貝和淺拷貝之前,我們需要先了解一下Javascript得數據類型。衆所周知JavaScript得數據類型,分爲基本數據類型和引用數據類型。那麼這兩種類型到底有什麼區別?接下來我們詳細的談談。
導圖:
js內存
接下來我們還需要了解一個重要的知識點----js中的內存
js中的內存爲兩種-----棧和堆。
基本數據類型存儲
基本數據類型的值存在棧裏面,並且值與值之間獨立存在,修改一個值,不會影響其他的值。舉個列子:把a的值傳給b
下面解釋爲什麼當a的值變爲124時,b爲什麼不改變
可以看出a和b的值相互獨立,當代碼執行到a++時,只是a的值變爲124,而b也是123
引用數據類型存儲:
- 對象保存在堆內存中
- 每創建一個新的對象就會在堆內存開闢一個新的空間
- 變量保存的是內存地址(對象引用)
- 兩個變量保存同一個引用,一個變量修改屬性時,另一個變量屬性值也會變化
引用數據類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中獲得實體。
舉例說明:
當obj屬性name變爲"孫悟空"時,obj1屬性name也變爲"孫悟空"
內存分析——解釋上述現象
當棧存放引用類型時,值爲對象的地址,obj與obj1指向同一個地址,所以當obj的name值變爲“孫悟空”時,obj1也會發生變化
看完這個,相信小夥伴們已經很清晰的明白,爲什麼會有淺拷貝和深拷貝這兩兄弟了吧。那麼這兩個到底有什麼區別尼?彆着急,我們一步一步道來。
深拷貝和淺拷貝的區別
深拷貝和淺拷貝是隻針對Object和Array這樣的引用數據類型的。示意圖大致如下:
淺拷貝只複製指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。
賦值和淺拷貝的區別
當我們把一個對象賦值給一個新的變量時,賦的其實是該對象的在棧中的地址,而不是堆中的數據。也就是兩個對象指向的是同一個存儲空間,無論哪個對象發生改變,其實都是改變的存儲空間的內容,因此,兩個對象是聯動的。
淺拷貝是按位拷貝對象,它會創建一個新對象,這個對象有着原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內存地址(引用類型),拷貝的就是內存地址 ,因此如果其中一個對象改變了這個地址,就會影響到另一個對象。即默認拷貝構造函數只是對對象進行淺拷貝複製(逐個成員依次拷貝),即只複製對象空間而不復制資源。
我們先來看兩個例子,對比賦值與淺拷貝會對原對象帶來哪些改變?
上面例子中,obj1是原始數據,obj2是賦值操作得到,而obj3淺拷貝得到。我們可以很清晰看到對原始數據的影響,具體請看下錶:
淺拷貝的實現方法
- 1、Object.assign()
Object.assign()方法可以將任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然後返回目標對象。但是該方法拷貝的時候是淺拷貝,拷貝的是對象的屬性的引用,並不是對象本身。(注意:當object只有一層的時候,就是淺拷貝)
- 2、Array.prototype.concat()
- 3、Array.prototype.slice()
深拷貝的實現方法
- 1、JSON.parse(JSON.stringify())
JSON.stringify()是前端開發過程中比較常用的深拷貝方式。原理是把一個對象序列化成爲一個JSON字符串,將對象的內容轉換成字符串的形式再保存在磁盤上,再用JSON.parse()反序列化將JSON字符串變成一個新的對象。
- 2、自己遞歸實現一個簡單深拷貝
深拷貝,主要用到的思想是遞歸,遍歷對象、數組直到裏邊都是基本數據類型,然後再去複製,就是深度拷貝。
示例代碼:
//定義檢測數據類型的功能函數
function isObject(obj) {
return typeof obj === 'object' && obj != null;
}
function cloneDeep(source) {
if (!isObject(source)) return source; // 非對象返回自身
var target = Array.isArray(source) ? [] : {};
for(var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (isObject(source[key])) {
target[key] = cloneDeep(source[key]); // 注意這裏
} else {
target[key] = source[key];
}
}
}
return target;
}
- 3、第三方深拷貝庫
參考
- https://segmentfault.com/a/1190000018874254
歡迎大家關注我的公衆號,一起交流進步