解读 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

相关文章
相关标签/搜索