javascript 中 class 的私有 getter/setter 必须用 # 前缀定义,与私有字段配套且仅限类内访问;公共 getter/setter 包裹私有字段无法实现真正私有,weakmap 仅模拟存储而非私有访问器。

JavaScript 中 class 语法里不能用 private 关键字直接修饰 getter/setter(像 TypeScript 那样),但可以通过 # 私有字段(Private Fields) 实现真正的私有访问器,这是 ECMAScript 2022(ES13)正式标准化的特性。
使用 # 私有字段定义私有 getter/setter
私有字段以 # 开头,只能在类内部访问。getter 和 setter 必须操作同名的私有字段,且自身也必须是私有的(即方法名也要加 #)。
- 私有 getter/setter 的名称必须以
#开头,与私有字段名一致或不同均可,但逻辑上通常配套使用 - 不能在类外部读写
#开头的属性或调用#开头的方法 - 私有字段和私有方法在类内可自由互访
示例:
class Counter {
#value = 0;
<p>// 私有 getter:只允许类内部读取 #value
get #rawValue() {
return this.#value;
}</p><p>// 私有 setter:只允许类内部修改 #value
set #rawValue(v) {
if (typeof v === 'number' && v >= 0) {
this.#value = v;
}
}</p><p>// 公共方法中使用私有访问器
increment() {
this.#rawValue = this.#rawValue + 1; // ✅ 合法:类内调用
}</p><p>getValue() {
return this.#rawValue; // ✅ 合法:类内读取
}
}</p><p>const c = new Counter();
c.increment();
console.log(c.getValue()); // 1
// console.log(c.#rawValue); // ❌ SyntaxError:无法在类外访问
// c.#rawValue = 10; // ❌ 同样报错</p>注意:不能用 public getter/setter 包裹私有字段来“模拟”私有访问器
有人尝试这样写:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
class BadExample {
#value = 42;
get value() { return this.#value; } // ❌ 这是公共 getter!
set value(v) { this.#value = v; } // ❌ 这是公共 setter!
}
这看似“保护了字段”,但实际 value 是公开可读写的——外部仍能自由调用 obj.value = 100。它只是把访问路径从 .#value 换成了 .value,并未实现访问控制。
替代方案:闭包 + WeakMap(仅用于旧环境兼容)
若需支持不支持 # 字段的环境(如 IE 或较老 Node.js),可用 WeakMap 模拟私有状态:
const privateStore = new WeakMap();
<p>class LegacyCounter {
constructor() {
privateStore.set(this, { value: 0 });
}</p><p>get value() {
return privateStore.get(this).value;
}</p><p>set value(v) {
if (typeof v === 'number') {
privateStore.get(this).value = v;
}
}
}</p>⚠️ 注意:这种写法的 get value() 仍是公共的,只是底层存储不可直接访问。真正“私有访问器”的语义(即 getter/setter 本身不可见)只有 # 语法能提供。
总结关键点
- 标准方式:用
#前缀定义私有字段 + 私有 getter/setter 方法 - 私有访问器必须是类内部方法,名称带
#,且只能被同类其他方法调用 - 不要混淆“私有字段”和“公共访问器包装私有字段”——后者不等于私有访问器
- 目前所有主流浏览器(Chrome 74+、Firefox 91+、Safari 14.1+)及 Node.js 14.6+ 均已支持
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










