JavaScript WeakMap
语言实现
比较无聊,不谈
怎么 polyfill
分析:
- 不能阻止 key 被 gc,因此,WeakMap 中不能直接持有 key。
- 通过 key 能找到 value,因为上条,不能由 WeakMap 或第三方对象去维护这种对应关系,于是只能在 key 中用某种方式去引用 value 来维持对应关系。
- 基于上条,得出 key 必须为对象的结论。
- 同一个对象能作为多个 WeakMap 的 key 分别引用不同的 value,这意味着 key 必须能识别不同的 WeakMap,因此,WeakMap 实现中,必须有个唯一标识,key 使用不同 WeakMap 的唯一标志作为属性名去引用不同的 value。
- 由于 WeakMap 不负责存储 key、value,所以 WeakMap 无法实现遍历 key、value 等操作。只能实现 get, set, has, delete 等方法去操作 key 中存储的数据。
基于这些分析,
我们可以这样来实现:
- 每个 WeakMap 构造时,生成一个唯一 id(Symbol 防冲突)。
- 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)
}
}
全文完