JavaScript私有字段用#前缀声明,ECMAScript 2022正式支持,真正阻止外部访问;仅类内可访问,不被子类继承;区别于下划线约定或闭包,原生高效且类型工具可校验。

JavaScript 的 class 语法中,私有字段(Private Fields)使用 # 前缀声明,这是目前标准且最直接的私有数据保护方式(ECMAScript 2022 正式支持)。它能真正阻止外部访问和修改,不是靠命名约定或闭包模拟。
用 # 声明私有字段和私有方法
在类体内,以 # 开头的标识符即为私有成员,只能在该类的内部方法中访问:
- 私有字段:如
#count、#name - 私有方法:如
#validate()、#logInternal() - 私有 get/set 访问器也支持:
get #value() { ... }
示例:
class Counter {
#count = 0; // 私有字段,初始化为 0
#step = 1;
<p>constructor(step = 1) {
this.#step = step;
}</p><p>increment() {
this.#count += this.#step;
}</p><p>getCount() {
return this.#count; // ✅ 允许内部读取
}</p><p>reset() {
this.#count = 0; // ✅ 允许内部写入
}</p><h1>log() { // ✅ 私有方法</h1><pre class="brush:php;toolbar:false;">console.log(`Current: ${this.#count}`);} }
const c = new Counter(2); c.increment(); console.log(c.getCount()); // 2 console.log(c.#count); // ❌ SyntaxError:无法访问私有字段
私有字段不能被子类继承或访问
即使子类继承了父类,也无法访问父类的私有字段或私有方法:
立即学习“Java免费学习笔记(深入)”;
-
super.#privateField会报错 - 子类实例上不存在
#开头的属性(连in、hasOwnProperty都检测不到) - 这确保了封装边界严格,避免意外覆盖或误用
例如:
class SecureCounter extends Counter {
peek() {
return this.#count; // ❌ 报错:私有字段未定义
}
}
与传统“伪私有”方式的区别
过去常用下划线前缀(如 _value)或闭包模拟私有,但它们都不具备真正保护能力:
-
_value:只是约定,外部仍可随意读写,IDE 或 linter 可能警告,但不阻止 - 闭包方式(如在构造函数内用
let value+ 闭包方法):能隐藏,但每个实例多一份函数副本,内存开销大,且无法在原型方法中使用 -
#字段:由引擎原生支持,存储在实例内部插槽中,性能接近公有字段,语法简洁,类型工具(如 TypeScript)也能识别并校验
注意事项和兼容性
使用私有字段需注意:
- 必须在类体顶层声明(不能在方法里动态创建
this.#x) - 不能用计算属性名:
[#key]❌ 不合法;[someSymbol]✅(但那是 Symbol 私有,非 # 语法) - 主流浏览器(Chrome 74+、Firefox 90+、Safari 14.1+)及 Node.js 14.6+ 均已支持
- TypeScript 3.8+ 完全支持,并会在编译时检查访问合法性


















