weakmap 是实现 javascript 真正私有属性的可靠方式,因其键为弱引用对象、不可遍历且不导致内存泄漏,配合模块作用域和闭包可安全封装私有数据。

WeakMap 是 JavaScript 中实现真正私有属性封装的可靠方式,因为它能避免内存泄漏,且外部无法直接访问存储的数据。
WeakMap 的核心特性支撑私有性
WeakMap 的键必须是对象,且对键对象是弱引用——当对象不再被其他变量引用时,WeakMap 中对应的条目会自动被垃圾回收。这既保证了数据与对象生命周期一致,又杜绝了因缓存导致的内存泄漏。更重要的是,WeakMap 的键和值都无法被遍历(没有 keys()、values()、entries() 方法),外部代码无法探测或枚举其中的内容,天然形成“隐藏”效果。
用 WeakMap 模拟私有字段的标准模式
通常将 WeakMap 实例定义在模块作用域(如 IIFE 或 ES 模块顶层),然后在构造函数或类方法中用 this 作为键存取私有数据:
const privateData = new WeakMap();
<p>class Person {
constructor(name, age) {
// 将私有数据绑定到当前实例
privateData.set(this, { name, age });
}</p><p>getName() {
return privateData.get(this).name;
}</p><p>setName(newName) {
privateData.get(this).name = newName;
}</p><p>getAge() {
return privateData.get(this).age;
}
}</p>注意:privateData 必须不暴露在类外部;所有访问都通过实例方法间接进行,this 作为键确保每个实例拥有独立的私有状态。
配合闭包增强封装与类型安全
可进一步用闭包包裹 WeakMap,防止意外覆盖或误用:
const createPrivateStore = () => {
const store = new WeakMap();
return {
get: (obj) => store.get(obj),
set: (obj, data) => store.set(obj, data),
has: (obj) => store.has(obj)
};
};
<p>const privates = createPrivateStore();</p><p>class BankAccount {
constructor(initial) {
privates.set(this, { balance: initial });
}</p><p>deposit(amount) {
const p = privates.get(this);
p.balance += amount;
}</p><p>getBalance() {
return privates.get(this).balance;
}
}</p>这种写法让私有存储逻辑更内聚,也便于在多个类间复用同一套私有管理机制。
对比 # 私有字段语法的适用场景
ES2022 引入的 # 语法(如 #balance)语法更简洁,但存在限制:只能在类内部使用,不能动态生成私有名,也无法在子类中直接访问父类的 # 字段(除非显式暴露 getter)。而 WeakMap 方案支持动态键名、运行时计算、跨类协作,适合需要高度灵活性或兼容旧环境(如需支持 IE 或 Node.js
若项目环境允许,# 语法是首选;若需动态控制、运行时策略或强隔离,WeakMap 仍是不可替代的底层工具。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











