weakmap 是实现 javascript 真正私有属性的核心工具,其键必须为对象且弱引用,支持实例绑定与自动清理;需在类外声明、以 this 为键存私有对象,原型方法通过 get(this) 访问,避免反向强引用和重复 set,相比闭包和 symbol 更隐蔽轻量且无内存泄漏风险。

WeakMap 是 JavaScript 中实现真正私有属性的核心工具之一。它不提供对外暴露的遍历接口,键必须是对象且为弱引用,天然适配“实例绑定 + 自动清理”的私有数据管理需求。
用 WeakMap 绑定实例与私有数据
关键在于把类实例(this)作为键,把一个普通对象作为值存入 WeakMap。这个值对象里放所有不想被外部访问的字段,比如 _token、_createdAt 或内部状态标记。
- WeakMap 必须声明在类外部作用域(如模块顶层),所有实例共享同一个实例,不能在构造函数或方法里重复创建
- 每个 new 出来的对象自动成为独立的键,彼此私有数据完全隔离
- 外部代码拿不到 WeakMap 引用,也就无法 get() 到任何私有值
原型方法安全访问私有数据
把 getter/setter 方法定义在原型上,避免每个实例重复创建函数;方法体内通过 privateData.get(this) 拿到对应实例的私有数据对象。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 这样既复用了方法逻辑,又保证了数据封装——this 是唯一能触发 get 的钥匙
- 不要在私有数据对象里反向强引用 this(比如
{ owner: this }),否则会阻碍 GC 回收 - 建议统一用一个对象承载多个私有字段,而不是为每个字段建单独 WeakMap
避开常见陷阱
WeakMap 看似简单,但几处细节错一点,封装就失效或引发内存泄漏。
- 键必须是真实存在的对象:DOM 节点要先判断
node instanceof Node,类实例要确保不是 null/undefined - 不能用字符串、数字、null 等原始值当键,WeakMap 会直接抛
TypeError - 不要在方法中调用
set(this, ...)覆盖已有私有数据——初始化只做一次,在 constructor 里完成 - WeakMap 不管值的生命周期:如果私有数据里存了定时器回调或事件监听器,仍需手动清理,否则值本身会造成泄漏
对比其他方案的优势
相比闭包方式(每个实例自带方法)或 Symbol 属性(可被 Object.getOwnPropertySymbols() 枚举),WeakMap 更轻量也更隐蔽。
- 闭包模式浪费内存:1000 个实例 = 1000 份相同方法函数
- Symbol 属性虽不可枚举,但依然可通过反射手段访问,不算真正私有
- WeakMap 值无法被 for...in、JSON.stringify、Object.keys() 触及,连调试器都看不到(除非你持有 WeakMap 引用)
- 实例销毁后条目自动失效,无需手动 delete,彻底规避内存泄漏风险
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










