WeakMap 的 key 必须是对象,因为弱引用仅对对象生效;原始值无内存地址,无法被 GC 追踪,用其作 key 会抛 TypeError。

WeakMap 不是 “轻量版 Map”,而是专为避免内存泄漏设计的弱引用键值结构 —— 它不“保管”对象,只“附着”数据。
为什么 WeakMap 的 key 必须是对象?
因为弱引用(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是原始值,不是对象)
WeakMap 为何不能遍历、没有 size、也不能用数组初始化?
这是弱引用机制的必然代价:GC 可能在任意时刻回收 key,而遍历、size 或构造时的批量读取,都需要“稳定快照”。如果允许这些操作,就等于要求引擎暂停 GC 或维护额外元数据 —— 违背了 WeakMap “零干预 GC”的设计哲学。
- ❌
wm.keys()、wm.values()、wm.entries()、wm.forEach()全部不存在 - ❌
wm.size属性不存在(连访问都会报undefined) - ❌
new WeakMap([['a', 1]])会报错 —— 构造器不接受可迭代参数 - ✅ 唯一安全的 API:只有
wm.set(key, value)、wm.get(key)、wm.has(key)、wm.delete(key)
什么时候该用 WeakMap?典型场景和常见踩坑
核心判断标准:你是否希望“数据随对象一起消失”?如果是,WeakMap 就是唯一选择;否则,用 Map 更稳妥。
本文档是python学习笔记与简明教程;为什么用Python作为编程入门语言?每种语言都会有它的支持者和反对者。去Google一下“why python”,你会得到很多结果,诸如应用范围广泛、开源、社区活跃、丰富的库、跨平台等等等等,也可能找到不少对它的批评,格式死板、效率低、国内用的人很少之类。不过这些优缺点的权衡都是程序员们的烦恼。作为一个想要学点编程入门的初学者来说,简单才是最重要的。当学C++的同学还在写链表,学Java的同学还在折腾运行环境的时候,学Pyt
立即学习“Java免费学习笔记(深入)”;
- ✅ 推荐场景:
– 给 DOM 元素附加私有状态(如isDragging),页面移除元素后自动清理
– 实现类的私有字段(配合闭包或模块作用域)
– 缓存计算结果,但不想阻止输入对象被回收(例如大型 canvas 图像处理中间结果) - ⚠️ 常见踩坑:
– 把wm.get(obj)的返回值当成“对象还活着”的依据 —— 实际上,只要obj被 GC,wm.get(obj)就返回undefined,且你无法提前感知
– 在异步回调中反复用同一个临时对象作 key:setTimeout(() => wm.get({x:1}), 100),每次都是新对象,查不到旧值,也留不下痕迹
– 误以为 WeakMap 能替代 Symbol 作为私有属性名 —— 它们解决的是不同问题:Symbol 防枚举,WeakMap 防内存泄漏
WeakMap 最难理解的地方不在语法,而在它“不可观测”的特性:你永远无法知道某个 key 是否还在里面,也无法知道它还有多少条目。这种“放手不管”的设计,恰恰是它最强大的地方 —— 也是最容易误用的起点。










