WeakMap 是实现 JavaScript 对象实例私有状态的理想工具,因其键为弱引用对象,可自动清理内存且不可枚举遍历;仅支持 get、set、has、delete 方法,适合以实例为键存储私有数据,并可通过闭包封装复用,比 Symbol 和闭包方案更安全高效。

WeakMap 是 JavaScript 中实现对象实例私有状态的理想工具,核心在于它对键的弱引用特性——键对象被回收时,对应的条目自动消失,避免内存泄漏,同时外部无法通过枚举或遍历访问其内容。
用 WeakMap 存储实例专属数据
WeakMap 的键必须是对象,且仅支持 get、set、has、delete 四个方法,不提供 keys()、values() 或 entries()。这天然屏蔽了对外暴露私有状态的可能。
典型用法是:将类实例本身作为键,把私有字段(如缓存、配置、内部计数器)存在 WeakMap 中。
- 每次构造函数中调用
privateData.set(this, { count: 0, cache: new Map() }) - 在实例方法里用
privateData.get(this)获取对应私有对象 - 无需手动清理——当 this 被垃圾回收,WeakMap 中该条目自动失效
封装成可复用的私有状态工厂
为避免每个类都声明独立 WeakMap,可用闭包封装一个私有状态管理器:
立即学习“Java免费学习笔记(深入)”;
const createPrivateState = () => {
const store = new WeakMap();
return {
get(obj) { return store.get(obj) ?? (store.set(obj, {}), store.get(obj)); },
has(obj) { return store.has(obj); },
delete(obj) { return store.delete(obj); }
};
};
这样多个类可共享同一套机制,又互不干扰——因为 WeakMap 的键是对象引用,不同实例不会冲突。
与 Symbol 或闭包方案对比
相比用 Symbol 属性模拟私有字段(this[PRIVATE_SYMBOL] = value),WeakMap 更安全:Symbol 属性仍可通过 Object.getOwnPropertySymbols() 和反射手段访问;而 WeakMap 完全不可枚举、不可遍历。
相比闭包方式(在构造函数内定义变量并返回闭包方法),WeakMap 支持在原型方法中访问私有状态,更符合面向对象设计习惯,也避免了每次实例化都创建新函数的开销。
注意 WeakMap 的局限性
WeakMap 不是万能的“私有字段替代品”:
- 不能用基本类型(如字符串、数字)作键,只能是对象
- 无法获取当前存储了多少条目,也不能清空全部内容
- 调试困难——开发者工具通常不显示 WeakMap 内容,需靠业务逻辑日志辅助验证
- 若误将同一对象多次传入
set,会覆盖而非合并,需自行保证初始化逻辑正确


















