WeakSet 能不能用来监听 DOM 元素的销毁?

Designer°辽源 阅读 4

我在做一个组件库,想用 WeakSet 来跟踪哪些 DOM 元素已经被移除了,但发现好像没法判断元素是否还在页面上。WeakSet 不是自动清理的吗?为什么我没法知道它什么时候被清掉了?

比如我这样写:

const observedNodes = new WeakSet();

function observe(node) {
  observedNodes.add(node);
}

// 后面想检查 node 是否还在 observedNodes 里
// 但即使 node 已经从 DOM 移除,observedNodes.has(node) 还是 true

是不是我对 WeakSet 的理解有误?它根本不能用来做这种“监听销毁”的事情?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
Tr° 子荧
你对 WeakSet 的理解有点偏差,它确实不是用来做这件事的。

先说说 WeakSet 的特性

WeakSet 的核心特点是"弱引用",也就是说它不会阻止垃圾回收。当一个对象只被 WeakSet 引用,而没有被其他地方引用时,GC 会把它回收掉,WeakSet 里就找不到它了。

但问题在于:GC 什么时候运行是浏览器决定的,你无法监听也无法控制。而且 DOM 元素被从页面移除后,它仍然存在于内存中啊,除非你也断开所有对它的引用,否则它不会被回收。你只是把 node 从 DOM 移除了,又不是把它置为 null,observedNodes 依然持有对它的引用,所以 has 肯定还是 true。

那怎么监听 DOM 元素的销毁呢

正确的做法是用 MutationObserver,这货就是专门用来监听 DOM 变化的。

// 创建一个观察器实例
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
// 检查被移除的节点
if (mutation.type === 'childList') {
mutation.removedNodes.forEach((removedNode) => {
// removedNode 就是被从 DOM 移除的节点
console.log('节点被移除了:', removedNode);

// 如果你想检查特定元素
if (removedNode === yourTargetElement) {
console.log('目标元素被移除了');
}
});
}
}
});

// 开始观察某个容器节点
observer.observe(document.body, {
childList: true, // 监听子节点的添加和移除
subtree: true // 同时监听所有后代节点
});

// 如果不再需要观察了,可以调用
// observer.disconnect();


MutationObserver 会实时通知你 DOM 节点什么时候被移除了,这才是你想要的功能。

总结一下

WeakSet 适合的场景是:你想让某些对象在没有被其他地方引用时自动被回收(比如缓存一些不重要的数据)。但它不适合用来"监听"某个东西,因为 WeakSet 本身不提供任何通知机制。

做 DOM 销毁监听,用 MutationObserver 就对了。
点赞
2026-03-12 16:01