JavaScript中WeakMap与WeakSet的应用场景及相关问题咨询
WeakMap & WeakSet 实用解析
1. 能解决哪些核心问题?
- 避免内存泄漏:依托弱引用特性,当WeakMap的键、WeakSet的值被垃圾回收时,对应的集合条目会自动移除,无需手动清理,解决了普通Map/Set因强引用导致的无用数据滞留问题。
- 关联对象私有数据:给对象附加额外状态或数据,既不污染对象自身属性,也不会因对象被回收而残留无效数据。
- 轻量化自动缓存:针对对象的计算结果做缓存,对象销毁后缓存自动失效,省去了维护缓存清理逻辑的麻烦。
2. 和普通Map/Set的核心区别
| 特性 | WeakMap/WeakSet | Map/Set |
|---|---|---|
| 引用类型 | 弱引用,不影响垃圾回收 | 强引用,会阻止键/值被回收 |
| 键/值限制 | WeakMap键必须是对象;WeakSet值必须是对象 | 支持任意类型(原始值/对象) |
| 遍历能力 | 不支持(无keys()/values()等方法,无法用for...of遍历) | 完全支持各类遍历操作 |
| 垃圾回收影响 | 键/值被回收时,对应条目自动删除 | 只要集合存在,键/值就不会被回收 |
| 大小获取 | 无size属性 | 有size属性可直接获取长度 |
3. 实际应用场景 & 示例
场景1:DOM元素附加私有状态
给DOM元素绑定状态数据,既不污染DOM属性,元素被移除后数据自动回收:
const elementState = new WeakMap(); const submitBtn = document.getElementById('submit-btn'); // 给按钮绑定点击计数 elementState.set(submitBtn, { clickCount: 0 }); submitBtn.addEventListener('click', () => { const state = elementState.get(submitBtn); state.clickCount++; console.log(`累计点击:${state.clickCount}`); }); // 当submitBtn被从DOM移除并触发垃圾回收后,elementState里的对应条目会自动消失
场景2:对象计算结果自动缓存
缓存对象的耗时计算结果,对象销毁后缓存自动清理:
const calcCache = new WeakMap(); function computeTotal(obj) { if (calcCache.has(obj)) { return calcCache.get(obj); } // 模拟耗时计算 const total = Object.values(obj).reduce((sum, num) => sum + num, 0); calcCache.set(obj, total); return total; } const stats = { views: 100, likes: 20 }; console.log(computeTotal(stats)); // 120 console.log(computeTotal(stats)); // 直接取缓存值120 // 当stats被置为null,垃圾回收后calcCache里的对应条目会自动删除 stats = null;
场景3:跟踪活跃对象集合
跟踪当前活跃的组件实例,组件销毁后自动从集合中移除:
const activeInstances = new WeakSet(); class PageComponent { constructor() { activeInstances.add(this); } destroy() { // 无需手动从activeInstances删除,this被回收后会自动移除 } } const header = new PageComponent(); const footer = new PageComponent(); console.log(activeInstances.has(header)); // true // 销毁实例 header = null; // 垃圾回收后,activeInstances中不再包含header
内容的提问来源于stack exchange,提问作者King是太阳
相关产品推荐
相关产品推荐

