「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

原文 COPYING OBJECTS IN JAVASCRIPT 地址: https://smalldata.tech/blog/2018/11/01/copying-objects-in-javascript

在這篇文章中,我們將會來了解一下JavaScript中對象複製的一些方法,我們將會看到淺複製以及深複製。

在我們開始之前,得先提到一些基礎知識:Javascript中的對象只是內存中某個位置的引用。 這些引用是可變的,即它們可以被重新分配。 因此,簡單地複製了個引用只會導致這兩個引用指向了內存中的相同位置:

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

正如你在上面的示例中所看到的,foo和bar都反映出了任一對象中所做的變化。 因此,在JavaScript中複製對象的時候根據不同的用例需要多加註意。

淺複製

如果你的對象中只有值類型的屬性,你可以使用擴展語法或者Object.assign():

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

注意,上述兩種方法同樣可以應用於將屬性值從多個源對象複製到目標對象:

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

上述方法的問題在於,對於那些具有對象類型的屬性的對象,只有引用被複制了,即它相當於執行了var bar = foo; 與第一個示例代碼一樣:

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

深複製(帶坑)

為了深層複製對象,一個可行的解決方案是先將對象序列化為字符串,然後再將其反序列化回來:

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

遺憾的是,此方法僅在源對象包含可序列化的值類型且沒有任何循環引用時才有效。不可序列化值類型的一個例子是Date對象,它以非ISO標準格式打印並且無法解析回其原始值 :( 。

深複製(較少坑)

對於更復雜的情況,有一個利用了新的HTML5克隆算法叫“structured clone”的。遺憾的是,寫此文時,它仍然侷限於某些內置類型,但它支持比JSON.parse更多的類型:Date,RegExp,Map,Set,Blob,FileList,ImageData,稀疏和類型數組。 它還保留了克隆數據中的引用,並且支持上述提到的序列化方法所不支持的循環和遞歸結構。

目前,沒有直接的方法來調用structured clone算法,但是有一些較新的瀏覽器特性在底層使用了這種算法。 因此,有一些變通方法可能用於對象的深複製。

MessageChannels: 這背後的思路是利用通信功能來應用序列化算法。 由於此功能是基於事件的,因此生成的克隆也是異步操作。

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

history API: history.pushState()和history.replaceState()都用第一個參數創造了結構化克隆! 注意,由於此方法是同步的,而且操作瀏覽器歷史記錄並不是一項能快速完成的操作,反覆調用此方法可能會導致瀏覽器無響應。

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

notification API: 在創建新通知時,構造函數會創建其關聯數據的結構化克隆。 注意,它還會嘗試向用戶顯示瀏覽器通知,但除非應用程序已請求顯示通知的權限,否則將以靜默方式失敗。 在得到權限的情況下,通知會立即關閉。

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

Node.js中的深複製

呃,又表示遺憾了,結構化克隆算法目前僅適用於基於瀏覽器的應用程序。 對於服務器端,可以使用lodash的cloneDeep方法,該方法大致上基於結構化克隆算法。

結論

總而言之,在JavaScript中複製對象的最佳算法在很大程度上取決於你所要複製的對象類型及環境。 雖然lodash是通用的深複製功能最安全的選擇,但如果你自己動手,可能會得到更效率的實現,以下是一個簡單的深複製示例,它也支持Date對象類型:

「譯」Copying Objects in JavaScript (JavaScript中的對象複製)

個人而言,我期待能夠在任何地方使用結構化克隆,然後可以不用再操心這些問題,快樂的克隆 :)

轉自百家號-國外優質文章翻譯(http://baijiahao.baidu.com/builder/preview/s?id=1616184334163227282)


分享到:


相關文章: