Javascript 深拷貝

前端-小強發表於2016-08-24

javascript深拷貝是初學者甚至有經驗的開發者,都會經常遇到問題,並不能很好的理解javascript的深拷貝。

深拷貝(deepClone)?

與深拷貝相對的就是淺拷貝,很多初學者在接觸這個感念的時候,是很懵逼的。

為啥要用深拷貝

在很多情況下,我們都需要給變數賦值,給記憶體地址賦予一個值,但是在賦值引用值型別的時候,只是共享一個記憶體區域,導致賦值的時候,還跟之前的值保持一直性。

看一個具體的例子

圖解:

這下就很好理解為什麼引用值型別資料相互影響問題。

實現

實現一個深拷貝函式,就不得不說javascript的數值型別。

判斷javascript型別

javascript中有以下基本型別

型別 描述
undefined undefined型別只有一個值undefined,它是變數未被賦值時的值
null null型別也只有一個值null, 它是一個空的物件引用
Boolean Boolean有兩種取值true和false
String 它表示文字資訊
Number 它表示數字資訊
Object 它是一系列屬性的無序集合, 包括函式Function和陣列Array

使用typeof是無法判斷function和array的,這裡使用Object.prototype.toString方法。 預設情況下,每個物件都會從Object上繼承到toString()方法,如果這個方法沒有被這個物件自身或者更接近的上層原型上的同名方法覆蓋(遮蔽),則呼叫該物件的toString()方法時會返回”[object type]”,這裡的字串type表示了一個物件型別

 實現deepClone

對於非引用值型別的數值,直接賦值,而對於引用值型別(object)還需要再次遍歷,遞迴賦值。


這裡有個點大家要注意下,對於function型別,博主這裡是直接賦值的,還是共享一個記憶體值。這是因為函式更多的是完成某些功能,有個輸入值和返回值,而且對於上層業務而言更多的是完成業務功能,並不需要真正將函式深拷貝。

但是function型別要怎麼拷貝呢?

其實博主只想到了用new來操作一下,但是function就會執行一遍,不敢想象會有什麼執行結果哦!o(╯□╰)o!其它暫時還沒有什麼好的想法,歡迎大家指導哦!

到這裡差不多也就實現完了深拷貝,又有人覺的怎麼沒有實現淺拷貝呢?

淺拷貝?

對於淺拷貝而言,可以理解為只操作一個共同的記憶體區域!這裡會存在危險!(。﹏。*) 。

如果直接操作這個共享的資料,不做控制的話,會經常出現資料異常,被其它部分更改。所以應該不要直接運算元據源,給資料來源封裝一些方法,來對資料來進行CURD操作。

到這裡估計就差不多了,但是作為一個前端,不僅僅考慮javascript本身,還得考慮到dom、瀏覽器等。

Element型別

來看下面程式碼,結果會返回啥呢?

答案是[object HTMLDivElement]

有時候儲存了dom元素, 一不小心進行深拷貝,上面的深拷貝函式就缺少了對Element元素的判斷。而判斷Element元素要使用instanceof來判斷。因為對於不同的標籤,tostring會返回對應不同的標籤的建構函式。

其它方式?

1. jquery的實現

詳見https://github.com/jquery/jquery/blob/master/src/core.js

2. underscore的實現

詳見https://github.com/jashkenas/underscore/blob/master/underscore.js

3. lodash的實現

詳見https://github.com/lodash/lodash/blob/master/lodash.js

4. JSON實現

先通過JSON.stringify一下,然後再JSON.parse一下,就能實現深拷貝。但是資料型別只支援基本數值型別。

小結

這裡大概總結了一下深拷貝,以及怎麼實現一個深拷貝。在不同的場景下,要根據業務場景,判斷是否需要使用深拷貝。

參考文獻

winter-JavaScript中的型別 http://www.cnblogs.com/winter-cn/archive/2009/12/07/1618281.html

本文連結 http://xiaoqiang730730.github.io/2016/08/21/javascriptDeepClone/

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

Javascript 深拷貝 Javascript 深拷貝

相關文章