WeakMap和WeakSet是JavaScript中的两种特殊的数据结构,它们都允许你以弱引用的方式存储对象。
WeakMap是一种映射数据结构,它的键必须是对象,而值可以是任意类型。WeakMap中的键是弱引用的,这意味着如果没有其他引用指向这个键对象,那么这个键对象及其关联的值会被垃圾回收器自动回收。这个特性使得WeakMap特别适合于创建和管理那些可能会被自动回收的对象。
WeakSet是一种集合数据结构,它的元素必须是对象。WeakSet中的元素是弱引用的,这意味着如果没有其他引用指向这个元素对象,那么这个元素对象会被垃圾回收器自动回收。这个特性使得WeakSet特别适合于创建和管理那些可能会被自动回收的对象。
请注意,由于WeakMap和WeakSet的元素或键是弱引用的,你不能遍历WeakMap的所有键和值,也不能遍历WeakSet的所有元素。这是因为垃圾回收器可能会在任何时候回收这些元素或键,因此遍历它们可能会导致不可预测的结果。
let sem = { name: "Semlinker" };
let map = new WeakMap();
map.set(sem, "xxx");
sem = null; // 覆盖引用
在这段代码中,你首先创建了一个对象sem,然后将这个对象作为键添加到WeakMap对象map中。然后,你将sem设置为null,这样原来的sem对象就没有其他引用指向它了。
由于WeakMap的键是弱引用的,当没有其他引用指向一个键对象时,这个键对象及其关联的值会被垃圾回收器自动回收。因此,理论上sem对象以及它在WeakMap中的对应项都可以被垃圾回收器自动回收。
然而,垃圾回收器何时运行,以及运行时会回收哪些对象,这是由垃圾回收器的具体实现决定的,我们无法从代码中直接控制。
此外,即使sem对象被垃圾回收了,WeakMap中的对应项也会被自动删除,但是我们无法从WeakMap中直接观察到这一点,因为WeakMap的键是不可枚举的,我们无法遍历WeakMap的所有键和值。
因此,即使你将sem设置为null,你也无法直接观察到sem对象是否已经被垃圾回收,以及WeakMap中的对应项是否已经被删除。
把代码复制到浏览器控制台中,我们可以比较直观的看到map的数值发生了变化。
由于WeakMap的键是弱引用,且不可枚举,所以WeakMap对象是无法被遍历的。这是WeakMap的设计原则之一,为了确保其键值对能够被垃圾回收,不会导致内存泄漏。
如果你需要遍历,可以考虑使用Map对象,Map对象的键是强引用,可以被遍历。但是,这样做的话,就需要手动管理内存,以防止内存泄漏。
如果你需要将对象作为键,并且需要遍历这些键,那么你可能需要重新考虑你的设计,或者使用其他数据结构,如Set或Array。基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。