weakmap 是实现弱关联的唯一可行载体,其键为弱引用对象,支持为 dom 元素等挂载私有元数据,但不可遍历、无 size、键不能为原始值。

不能直接用 Map 实现“弱关联”——Map 的键是强引用,只要键还在 Map 中,对应的对象就无法被垃圾回收。要实现弱关联,必须换用 WeakMap,它专为这种场景设计。
WeakMap 是唯一可行的底层载体
Map 会阻止其键对象被回收,哪怕该对象在其他地方已无任何引用。而 WeakMap 的键是弱引用:当一个对象仅作为 WeakMap 的键存在、别处再无强引用时,JavaScript 引擎可在下一次垃圾回收时自动清理该键及其对应值。这正是“弱关联”的本质——生命周期由外部持有者决定,不因索引存在而延长。
- 键必须是对象(不能是字符串、数字等原始值)
- 无法遍历、无法获取键列表、无法获知 size,这是弱引用的代价和保障
- 适合给已有对象“挂载私有元数据”,比如 DOM 元素的状态标记、类实例的缓存字段
典型弱索引构建方式:以 DOM 元素为例
你想为页面中的每个 元素记录上次输入时间,但不希望因索引存在导致元素无法卸载:
- 创建 WeakMap 实例:
const inputLastTime = new WeakMap(); - 绑定数据:
inputLastTime.set(inputEl, { timestamp: Date.now(), value: inputEl.value }); - 后续访问:
const meta = inputLastTime.get(inputEl);(若 inputEl 已被移除且无其他引用,get返回undefined)
避免常见误用陷阱
WeakMap 不是 Map 的轻量替代品,它的限制就是能力边界:
- 不要试图用字符串 ID 当键——必须传真实对象引用,否则报
TypeError - 不要期望通过 WeakMap 管理生命周期——它不触发回调,也不提供“键消失通知”,只能被动检查
has()或get() - 不要混合使用 Map 和 WeakMap 做同一类索引——语义冲突,维护成本高
进阶:组合 WeakMap + Symbol 实现更安全的私有字段
在类内部,可将 WeakMap 与闭包结合,模拟真正的私有属性:
- 在模块顶层定义
const privateData = new WeakMap(); - 构造函数中:
privateData.set(this, { _cache: null, _dirty: true }); - 所有实例方法通过
privateData.get(this)访问专属状态 - 实例销毁后,相关数据自动释放,无需手动清理










