解讀 webconponents.js 中對 ES6 WeakMap 的 shim (一)

ES6 中對 WeakMap 的要求主要是對 key(非 null 對象) 僅保留弱引用,且取值是 O(1) 複雜度,這致使了它的兩個特性:php

  • 不能求大小,更不能枚舉。
  • 當 key 對象不被其餘變量引用時,會被垃圾回收系統回收。

按說這種關乎內存管理的對象是無法 shim 的。可是webcomponents.js 對 WeakMap 有一個很奇妙的 shim。通過閱讀後整理原理如圖:git

WeakMap shim 原理

解說:github

  1. WeakMap 內不提供存儲 key 和 value 的區域,避免產生本對象對 key 的強引用。
  2. 每一個 WeakMap 中只存儲一個隨機、惟一輩子成的 name 字符串。
  3. 在 WeakMap 中的每個 key 中設置一個屬性:

    • 屬性名是 WeakMap 的惟一 name。
    • 值爲該 key 在 WeakMap 中對應的 value。
  4. 此時,獲取 WeakMap 中指定 key 對應的 value,就等價於獲取 key 中的 WeakMap::name 屬性的值。
  5. 爲了防止因爲原型繼承致使 WeakMap::name 屬性不是本對象自有的屬性,採用了一個技巧來保證獲取 WeakMap::name 屬性的值不是從原型繼承來的,這個技巧做爲另外一個文章再談。

    • 雖然使用 Object::hasOwnProperty 也能夠達到相同的效果,可是從庫的級別考慮,該屬性可能被第三方代碼污染,因此採用了更極端的方式來驗證。

經過這種引用方式,達成了 WeakMap 對象事實上沒有引用到 key 對象的效果,那麼當 key 對象不被別的變量引用時,就會被垃圾回收系統自動回收。同時取值也是 O(1) 複雜度的。web

相關文章
相關標籤/搜索