Skip to main content

WeakMap

WeakMap 是可被 垃圾回收 的值的集合,WeakMap 允许将数据与对象相关联。

WeakMap其中的 键 必须是 对象 和 非全局注册的符号, 值可以使用任意的Javascript 数据类型。

初始化​

可以给 WeakMap 构造函数 传入一个 Array 或者 可迭代对象。

const key1 = { id: 1 };
const key2 = { id: 2 };
const key3 = { id: 3 };

const weakMap = new WeakMap();

weakMap.set(key1, "value1").set(key2, "value2").set(key3, "value3");

console.log(weakMap.get(key1));
console.log(weakMap.get(key2));
console.log(weakMap.get(key3));

如果尝试使用 非对象设置 键, 会抛出 TypeError。

const weakMap = new WeakMap();

weakMap.set("key1", "value1");
// Uncaught TypeError: Invalid value used as weak map key

基本 API​

可以使用 set() 在添加 键值对。 set() 方法返回 WeakMap 实例, 因此 可以把 多个操作 连接 起来。

可以使用 get() 和 has() 进行查询。可以通过 size 属性获取 WeakMap 中键值对的数量。

可以使用 delete() 和 clear() 删除值。

const key1 = { id: 1 };
const key2 = { id: 2 };

const weakMap = new WeakMap();

console.log(weakMap.has(key1)); // false
console.log(weakMap.get(key2)); // undefined

weakMap.set(key1, "Matt");
weakMap.set(key2, "Frisbie");

console.log(weakMap.has(key1)); // true
console.log(weakMap.get(key2)); // Matt

weakMap.delete(key1);

console.log(weakMap.has(key1)); // false
console.log(weakMap.has(key2)); // true

弱键​

一个对象作为 WeakMap 的 键 存在 , 不会阻止垃圾回收。

如果一个对象作为 键 被回收, 那么在 WeakMap 中相应的值便成为了进行 垃圾回收 的候选对象。

set 方法() 初始化了一个新对象 , 并将它作用一个字符串的键。

因为没有指向这个对象的其他引用 , 所以当这段代码执行后 , 这个对象 键 就会被当作垃圾回收。

然后 这个键值对 就从 WeakMap中消失了。

const weakMap = new WeakMap();

weakMap.set({}, "value");

container 对象维护着一个 键 的引用, 因此这个对象键 不会成为垃圾回收的目标。

但是如果调用了removeReference(), 就会摧毁对象的最后一个引用, 垃圾回收就会把这个键值对清理掉。

const weakMap = new WeakMap();

const container = {
key: {},
};

weakMap.set(container.key, "value");

function removeReference() {
container.key = null;
}

不可迭代​

因为 WeakMap 中的 键 任何时候都有可能会被销毁,所以没有必要提供迭代键值对的能力。

使用 WeakMap​

私有数据存储​

const privateData = new WeakMap();

class MyClass {
constructor() {
privateData.set(this, { secret: 42 });
}

getSecret() {
return privateData.get(this).secret;
}
}

const instance = new MyClass();

console.log(instance.getSecret()); // 42

DOM 节点关联数据​

const nodeData = new WeakMap();

const node = document.getElementById("__docusaurus");
nodeData.set(node, 0);

node.addEventListener("click", () => {
let clicks = nodeData.get(node);
nodeData.set(node, ++clicks);
console.log(`Clicked ${clicks} times`);
});