Set
和 WeakSet
都保存对对象(如 obj1
)的引用,但它们处理这些引用的方式不同,这直接影响到垃圾回收的行为。
强引用 vs. 弱引用
-
强引用:当一个对象被
Set
引用时,Set
持有的是对该对象的强引用。这意味着只要Set
存在并且包含这个对象,JavaScript 的垃圾回收机制就不会回收这个对象,即使没有其他的变量引用它。因此,Set
中的对象会一直存在,直到你显式地从Set
中删除它或者清空Set
。 -
弱引用:
WeakSet
持有的是对象的弱引用。如果一个对象只被WeakSet
引用而没有其他强引用,那么这个对象可能会在任何时候被垃圾回收。WeakSet
不会阻止垃圾回收器回收这些对象,因此一旦对象不再有强引用,它就可能被移除并回收。
示例
让我们通过一个具体的例子来说明这两种行为:
// 创建两个对象
const obj1 = { name: 'Object 1' };
const obj2 = { name: 'Object 2' };
// 创建 Set 和 WeakSet 实例
const mySet = new Set();
const myWeakSet = new WeakSet();
// 将 obj1 和 obj2 分别添加到 Set 和 WeakSet 中
mySet.add(obj1);
myWeakSet.add(obj2);
// 清除 obj1 和 obj2 的所有外部引用
obj1 = null;
obj2 = null;
// 在这里,你可以使用浏览器的开发者工具或 Node.js 环境中的 gc() 函数来尝试触发垃圾回收。
if (global.gc) {
global.gc(); // 手动触发垃圾回收(仅在某些环境中有效)
}
// 检查垃圾回收后的状态
setTimeout(() => {
console.log('After attempting garbage collection:');
// 对于 Set,obj1 仍然存在,因为它持有强引用
console.log('Set size:', mySet.size); // 输出 1 或 0,取决于垃圾回收是否发生
for (let item of mySet) {
console.log('Set contains:', item.name); // 如果 obj1 还未被回收,输出 "Object 1"
}
// 对于 WeakSet,obj2 可能已经被垃圾回收,因为它只持有弱引用
console.log('WeakSet has obj2:', myWeakSet.has(obj2)); // 输出 false,因为 obj2 已经被设置为 null
}, 0);
解释
-
Set
的行为:obj1
被添加到Set
中后,Set
持有对obj1
的强引用。- 即使我们将
obj1
设置为null
,Set
仍然持有对原始对象的强引用,因此这个对象不会被垃圾回收。 - 如果我们遍历
Set
,我们仍然可以看到obj1
的内容(前提是垃圾回收尚未发生)。
-
WeakSet
的行为:obj2
被添加到WeakSet
中后,WeakSet
持有对obj2
的弱引用。- 当我们将
obj2
设置为null
时,obj2
没有其他强引用,因此它可以被垃圾回收。 - 垃圾回收发生后,
WeakSet
中的obj2
会被自动移除,myWeakSet.has(obj2)
会返回false
。
关键点
Set
:持有强引用,防止对象被垃圾回收,直到你显式地从Set
中删除对象或清空Set
。WeakSet
:持有弱引用,允许对象在没有其他强引用时被垃圾回收,WeakSet
会自动移除这些对象。
总结
Set
适合用于需要持久化存储对象的场景,确保对象不会被意外回收。WeakSet
适合用于临时关联数据或实现某种形式的私有化机制,避免内存泄漏,尤其是在你不希望对象长时间存在于内存中的情况下。
通过这种方式,你可以根据具体的需求选择合适的集合类型,以优化内存管理和数据结构的设计。
WeakSet不会阻止垃圾回收对象,只要这个对象没被任何地方强引用了,垃圾回收就会回收对象,不会去管WeakSet是否还用着这个对象。
标签:obj2,对象,回收,Set,引用,Weakset,WeakSet From: https://www.cnblogs.com/jocongmin/p/18656444