克隆

JavaScript 深拷貝性能分析(漢化版)
JavaScript 深拷貝性能分析html

Object.assign()

Object.assign 方法只會拷貝源對象自身的而且可枚舉的屬性到目標對象。該方法使用源對象的[[Get]]和目標對象的[[Set]],因此它會調用相關 getter 和 setter。算法

JSON.parse

過去瀏覽器內部傳遞的對象是使用JSON進行序列化的。 現代瀏覽器序列化將使用結構化克隆算法。這將會使更多對象能夠被安全的傳遞。segmentfault

JSON parse的優缺點

優勢瀏覽器

  • 代碼簡單安全

    const obj = /* ... */
    const copy = JSON.parse(JSON.stringify(obj))

缺點數據結構

  • 若是對象複雜,你可能建立一個臨時的,很大的字符串,只是爲了把它從新放回解析器。
  • 沒法解決處理循環對象, 如當您構建樹狀數據結構,其中一個節點引用其父級,而父級又引用其子級。異步

    const x = {};
    const y = {x};
    x.y = y; // Cycle: x.y.x.y.x.y.x.y.x...
    const copy = JSON.parse(JSON.stringify(x)); // throws!
  • 諸如 Map, Set, RegExp, Date, ArrayBuffer 和其餘內置類型在進行序列化時會丟失

結構化克隆算法

由於它支持包含循環圖的對象的序列化 ---對象能夠引用在同一個圖中引用其餘對象的對象。此外,在某些狀況下,結構化克隆算法可能比JSON更高效。
結構化算法優於JSON的地方ide

優於 JSON 的地方

  • 結構化克隆能夠複製 RegExp 對象。
  • 結構化克隆能夠複製 Blob、File 以及 FileList 對象。
  • 結構化克隆能夠複製 ImageData 對象。CanvasPixelArray

的克隆粒度將會跟原始對象相同,而且複製出來相同的像素數據。性能

  • 結構化克隆能夠正確的複製有循環引用的對象

結構化克隆所不能作到的

  • Error 以及 Function 對象是不能被結構化克隆算法複製的;若是你嘗試這樣子去作,這會致使拋出 DATA_CLONE_ERR 的異常。
  • 企圖去克隆 DOM 節點一樣會拋出 DATA_CLONE_ERROR 異常。
  • 對象的某些特定參數也不會被保留url

    • RegExp 對象的 lastIndex 字段不會被保留
    • 屬性描述符,setters 以及 getters(以及其餘相似元數據的功能)一樣不會被複制。例如,若是一個對象用屬性描述符標記爲 read-only,它將會被複製爲 read-write,由於這是默認的狀況下。
    • 原形鏈上的屬性也不會被追蹤以及複製。
    • symbols 不會被複制

MessageChannel

Channel Messaging API的Channel Messaging接口容許咱們建立一個新的消息通道,並經過它的兩個MessagePort 屬性發送數據。
圖片描述

消息通道的傳遞是異步的,使用結構化克隆算法。

Note: 此特性在 Web Worker 中可用。
兼容性以下:
圖片描述

History API

HTML5引入了 history.pushState()history.replaceState() 方法,它們分別能夠添加和修改歷史記錄條目。這些方法一般與window.onpopstate 配合使用。

  • pushState
    history.pushState(data({a: 'hi'}), name("tdy"), url("bar.html"))
    改變瀏覽器的url顯示,可是瀏覽器自己不會去作任何的改變。
  • history.replaceState() 參數和pushState一致,修改當前頁面的信息
  • window.onpopstate
    調用history.pushState()或者history.replaceState()不會觸發popstate事件. popstate事件只會在瀏覽器某些行爲下觸發, 好比點擊後退、前進按鈕(或者在JavaScript中調用history.back()、history.forward()、history.go()方法).信息保存在state屬性上

pushState或replaceState時須要複製一份狀態對象,這個狀態對象使用結構化克隆並且是同步的
最大儲存對象大小爲640KB。

Safari 瀏覽器對replaceState調用的限制數量爲 30 秒內 100 次
兼容性以下:
圖片描述

Notification API

簡潔明瞭

function structuralClone(obj) {
  return new Notification('', {data: obj, silent: true}).data
}

const obj = /* ... */
const clone = structuralClone(obj)

兼容性欠佳,而且,Safari 老是返回undefined。

圖片描述

最後

若是您沒有循環對象,而且不須要保留內置類型,則可使用跨瀏覽器的JSON.parse(JSON.stringify())得到最快的克隆性能。

若是你想要一個適當的結構化克隆,MessageChannel是你惟一可靠的跨瀏覽器的選擇。

相關文章
相關標籤/搜索