WeakMap 键必须是对象或 Symbol,因其依赖弱引用机制追踪内存地址标识,原始值无稳定身份和地址,无法被弱引用;尝试用字符串等原始值作键会抛出 TypeError。

WeakMap 要求键必须是对象(或自 ES2023 起支持 Symbol),这不是语法限制,而是由其底层“弱引用”机制决定的——只有对象才能被 JavaScript 引擎以弱引用方式持有。
为什么只能用对象(或 Symbol)作键
WeakMap 的核心目标是不干扰垃圾回收。原始值(如字符串、数字、布尔值)在 JS 中是按值传递、不可变且无内存地址概念的,引擎无法对其建立“弱引用”。只有对象(包括函数、数组、DOM 元素等)和 Symbol 具有独立的身份标识(identity)和内存生命周期,才可能被弱引用跟踪。
- 尝试用字符串作键:
wm.set("key", "value")→ 直接抛出TypeError: Invalid value used as weak map key - 原始值包装成对象可绕过(但不推荐):
wm.set(new String("key"), "value"),此时键是字符串包装对象,不是原始字符串本身 - Symbol 从 ES2023 开始被允许,因为 Symbol 值具有唯一性与对象级身份语义,满足弱引用前提
底层设计原因:弱引用依赖对象的身份语义
WeakMap 不保存对键的强引用,而是依赖引擎内部的“弱引用表”。这个表记录的是对象的内存地址标识(即 identity hash),而不是内容。当该地址不再被任何强引用指向时,GC 可安全回收它,同时 WeakMap 自动清理对应条目。
- 原始值没有稳定地址:
"abc"在不同位置出现可能是不同内存实例,也可能被常量池复用,无法可靠追踪生命周期 - 对象有唯一身份:即使两个对象字面量完全相同(
{a:1}和{a:1}),它们也是不同键;WeakMap 正是靠这个区分不同实例 - 这种设计让 WeakMap 天然适配“元数据绑定”场景——比如给某个 DOM 元素存私有配置,元素卸载即自动清理,零内存泄漏风险
对比 Map 就更清楚了
Map 允许任意类型作键,因为它用强引用维持键的存在,需要明确管理生命周期。而 WeakMap 放弃遍历能力(无 keys()、size)、放弃键类型灵活性,换来的是与 GC 协同工作的轻量机制。
立即学习“Java免费学习笔记(深入)”;
- Map 是“你负责生命周期,我负责存取”
- WeakMap 是“你不管,我跟着 GC 走”
- 所以 WeakMap 不是 Map 的简化版,而是为特定问题(绑定+自动清理)定制的专用结构


















