WeakMap 的 key 必须是对象,因为弱引用仅对对象生效;原始值无内存地址,无法被 GC 追踪,用其作 key 会抛 TypeError。
WeakMap 不是 “轻量版 M
ap”,而是专为避免内存泄漏设计的弱引用键值结构 —— 它不“保管”对象,只“附着”数据。
因为弱引用(WeakReference)在 JavaScript 中只对对象生效:原始值(如 "str"、42、true)没有内存地址,无法被 GC 追踪引用关系。一旦你尝试用原始值作 key,会立刻抛出错误:
const wm = new WeakMap();
wm.set('hello', 'world'); // TypeError: Invalid value used as weak map key
wm.set(123, {}); // 同样报错
{}、[]、new Date()、document.body、函数等一切继承自 Object 的值"a"、0、null、undefined、Symbol()(注意:Symbol 是原始值,不是对象)size、也不能用数组初始化?这是弱引用机制的必然代价:GC 可能在任意时刻回收 key,而遍历、size 或构造时的批量读取,都需要“稳定快照”。如果允许这些操作,就等于要求引擎暂停 GC 或维护额外元数据 —— 违背了 WeakMap “零干预 GC”的设计哲学。
wm.keys()、wm.values()、wm.entries()、wm.forEach() 全部不存在wm.size 属性不存在(连访问都会报 undefined)new WeakMap([['a', 1]]) 会报错 —— 构造器不接受可迭代参数wm.set(key, value)、wm.get(key)、wm.has(key)、wm.delete(key)
核心判断标准:你是否希望“数据随对象一起消失”?如果是,WeakMap 就是唯一选择;否则,用 Map 更稳妥。
isDragging),页面移除元素后自动清理wm.get(obj) 的返回值当成“对象还活着”的依据 —— 实际上,只要 obj 被 GC,wm.get(obj) 就返回 undefined,且你无法提前感知setTimeout(() => wm.get({x:1}), 100),每次都是新对象,查不到旧值,也留不下痕迹WeakMap 最难理解的地方不在语法,而在它“不可观测”的特性:你永远无法知道某个 key 是否还在里面,也无法知道它还有多少条目。这种“放手不管”的设计,恰恰是它最强大的地方 —— 也是最容易误用的起点。