• WeakMap是Map 的“兄弟”类型,其API也是Map的子集。
  • WeakMap中的”weak”(弱).描述的是JavaScript垃圾回收程序对待“弱映射”中键的方式。

基本API

  • 可以使用 new 关键字实例化一个空的 WeakMap:
1
const wm = new WeakMap();
  • 弱映射中的键只能是 Object 或者继承自 Object的类型,尝试使用非对象设置键会抛出TypeError。
  • 值的类型没有限制。
  • 如果想在初始化时填充弱映射,则构造函数可以接收一个可迭代对象,其中需要包含键/值对数组。可迭代对象中的每个键/值都会按照迭代顺序插人新实例中:
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
const key1 = {id: 1}, 
key2 = {id: 2},
key3 = {id: 3};
// 使用嵌套数组初始化弱映射
const wm1 = new WeakMap([
[key1, "val1"],
[key2, "val2"],
[key3, "val3"]
]);
alert(wm1.get(key1)); // val1
alert(wm1.get(key2)); // val2
alert(wm1.get(key3)); // val3
// 初始化是全有或全无的操作
// 只要有一个键无效就会抛出错误,导致整个初始化失败
const wm2 = new WeakMap([
[key1, "val1"],
["BADKEY", "val2"],
[key3, "val3"]
]);
// TypeError: Invalid value used as WeakMap key
typeof wm2;
// ReferenceError: wm2 is not defined
// 原始值可以先包装成对象再用作键
const stringKey = new String("key1");
const wm3 = new WeakMap([
stringKey, "val1"
]);
alert(wm3.get(stringKey)); // "val1"
  • 初始化之后可以使用set ()再添加键/值对,可以使用get ()和has()查询,还可以使用delete()删除:
1
2
3
4
5
6
7
8
9
10
11
12
const wm = new WeakMap(); 
const key1 = {id: 1},
key2 = {id: 2};
alert(wm.has(key1)); // false
alert(wm.get(key1)); // undefined
wm.set(key1, "Matt")
.set(key2, "Frisbie");
alert(wm.has(key1)); // true
alert(wm.get(key1)); // Matt
wm.delete(key1); // 只删除这一个键/值对
alert(wm.has(key1)); // false
alert(wm.has(key2)); // true

弱键

  • WeakMap 中“weak”表示弱映射的键不属于正式的引用,不会阻止垃圾回收;
  • 只要键存在,键/值对就会存在于映射中,并被当作对值的引用;
1
2
const wm = new WeakMap(); 
wm.set({}, "val");

set ()方法初始化了一个新对象并将它用作一个字符串的键。因为没有指向这个对象的其他引用,所以当这行代码执行完成后,这个对象键就会被当作垃圾回收。然后,这个键/值对就从弱映射中消失了,使其成为一一个空映射。在这个例子中,因为值也没有被引用,所以这对键/值被破坏以后,值本身也会成为垃圾回收的目标。

不可迭代键

  • 因为WeakMap中的键/值对任何时候都可能被销毁,所以没必要提供迭代其键/值对的能力。
  • WeakMap实例之所以限制只能用对象作为键,是为了保证只有通过键对象的引用才能取得值。