ES6 中對 WeakMap 的要求主要是對 key(非 null 對象) 僅保留弱引用,且取值是 O(1) 複雜度,這致使了它的兩個特性:php
- 不能求大小,更不能枚舉。
- 當 key 對象不被其餘變量引用時,會被垃圾回收系統回收。
按說這種關乎內存管理的對象是無法 shim 的。可是webcomponents.js 對 WeakMap 有一個很奇妙的 shim。通過閱讀後整理原理如圖:git
解說:github
- WeakMap 內不提供存儲 key 和 value 的區域,避免產生本對象對 key 的強引用。
- 每一個 WeakMap 中只存儲一個隨機、惟一輩子成的 name 字符串。
- 在 WeakMap 中的每個 key 中設置一個屬性:
- 屬性名是 WeakMap 的惟一 name。
- 值爲該 key 在 WeakMap 中對應的 value。
- 此時,獲取 WeakMap 中指定 key 對應的 value,就等價於獲取 key 中的 WeakMap::name 屬性的值。
- 爲了防止因爲原型繼承致使 WeakMap::name 屬性不是本對象自有的屬性,採用了一個技巧來保證獲取 WeakMap::name 屬性的值不是從原型繼承來的,這個技巧做爲另外一個文章再談。
- 雖然使用 Object::hasOwnProperty 也能夠達到相同的效果,可是從庫的級別考慮,該屬性可能被第三方代碼污染,因此採用了更極端的方式來驗證。
經過這種引用方式,達成了 WeakMap 對象事實上沒有引用到 key 對象的效果,那麼當 key 對象不被別的變量引用時,就會被垃圾回收系統自動回收。同時取值也是 O(1) 複雜度的。web