weakmap 是 javascript 中用于为对象附加私有元数据的弱引用集合,键必须是对象且不阻止垃圾回收,适合封装、缓存及模拟私有字段,但不可遍历、无 size、不支持序列化。

WeakMap 是 JavaScript 中专门用于为对象附加私有元数据的工具,它的核心特点是“弱引用”——不会阻止键对象被垃圾回收。这使得它非常适合在不干扰对象生命周期的前提下,安全地存储与对象绑定的额外信息。
为什么用 WeakMap 而不是普通 Map?
普通 Map 的键是强引用,只要对象作为键存在,它就无法被 GC 回收,容易造成内存泄漏。而 WeakMap 的键必须是对象(不能是原始值),且对键对象是弱引用:一旦该对象在外部完全不可达,WeakMap 中对应的条目会自动消失,无需手动清理。
- 适合给第三方对象、DOM 元素、或你无法控制生命周期的对象添加元数据
- 天然支持封装:WeakMap 实例通常定义在闭包中,外部无法访问,元数据真正私有
- 不能遍历、没有 size 属性、不支持 clear(),这些限制恰恰保障了安全性
典型用法:为对象挂载私有状态
常见场景是模拟私有属性或缓存计算结果。例如,为每个用户对象缓存其格式化后的全名:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const fullNameCache = new WeakMap();
function getFullName(user) {
if (fullNameCache.has(user)) {
return fullNameCache.get(user);
}
const name = `${user.firstName} ${user.lastName}`.trim();
fullNameCache.set(user, name);
return name;
}
const user1 = { firstName: 'Alice', lastName: 'Smith' };
console.log(getFullName(user1)); // "Alice Smith"
// user1 被释放后,fullNameCache 中对应条目自动失效
配合类实现真正的私有字段(ES2022 前方案)
在私有字段(#field)语法普及前,WeakMap 是实现类私有数据的标准模式:
const privateData = new WeakMap();
class Button {
constructor(element) {
// 将私有状态绑定到 element 实例
privateData.set(element, {
clickCount: 0,
lastClickTime: 0
});
element.addEventListener('click', () => this.handleClick(element));
}
handleClick(element) {
const data = privateData.get(element);
data.clickCount++;
data.lastClickTime = Date.now();
}
getClickCount(element) {
return privateData.get(element)?.clickCount || 0;
}
}
注意:这里把 element 当作键,而非 this(因为类实例可能被复用或暴露),确保元数据归属清晰、可预测。
关键限制和注意事项
- 键只能是对象(null 不行,原始值如字符串、数字也不行)
- 无法枚举键或值,不能获取所有条目,也不能判断 WeakMap 是否为空
- 不能用 JSON.stringify 或结构化克隆(如 postMessage)传递 WeakMap
- 调试时看不到内容——Chrome DevTools 显示为 WeakMap {size: ?},这是设计使然
不复杂但容易忽略:WeakMap 不是万能缓存,它只解决“对象级元数据绑定+自动清理”这一件事。需要持久化、可遍历或跨上下文共享的数据,应选其他方案。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










