语言实现

比较无聊,不谈

怎么 polyfill

分析:

  1. 不能阻止 key 被 gc,因此,WeakMap 中不能直接持有 key。
  2. 通过 key 能找到 value,因为上条,不能由 WeakMap 或第三方对象去维护这种对应关系,于是只能在 key 中用某种方式去引用 value 来维持对应关系。
  3. 基于上条,得出 key 必须为对象的结论。
  4. 同一个对象能作为多个 WeakMap 的 key 分别引用不同的 value,这意味着 key 必须能识别不同的 WeakMap,因此,WeakMap 实现中,必须有个唯一标识,key 使用不同 WeakMap 的唯一标志作为属性名去引用不同的 value。
  5. 由于 WeakMap 不负责存储 key、value,所以 WeakMap 无法实现遍历 key、value 等操作。只能实现 get, set, has, delete 等方法去操作 key 中存储的数据。

基于这些分析,

我们可以这样来实现:

  1. 每个 WeakMap 构造时,生成一个唯一 id(Symbol 防冲突)。
  2. key 中,以上述 Symbol 作为属性名,引用 value。

于是一个可行的实现的核心代码就顺理成章出来了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class WeakMap {
  _uid = Symbol()

  constructor(entries) {
    // 略
  }

  get(key) {
    return key[this._uid]
  }

  set(key, value) {
    Object.defineProperty(key, this._uid, {
      value: [key, value],
      configurable: true,
      enumerable: false,
      writable: true
    })
  }

  delete(key) {
    delete key[this._uid]
  }

  has(key) {
    return key.hasOwnProperty(this._uid)
  }
}


全文完