JavaScript中使用#符号定义私有属性和方法是ES2022标准化特性,具有真正运行时私有性:不可外部访问、不可枚举、不可继承,且必须在类体内声明并用this.#xxx访问,支持私有getter/setter及静态私有方法。

JavaScript 中使用 # 符号定义私有属性和私有方法,是 ES2022(TC39 Stage 4)正式标准化的特性,称为“类字段提案”中的私有字段(Private Fields)和私有方法(Private Methods)。它通过井号 # 前缀实现真正的运行时私有性——外部无法访问、不可枚举、不可继承,且在子类中也需用 # 显式访问。
私有属性:用 #name 语法声明和访问
私有属性必须在类体顶层声明(不能在方法内),名称以 # 开头。只能在类内部(包括构造函数、实例方法、getter/setter、私有方法)通过 this.#xxx 访问。
- 未声明直接使用会报
SyntaxError(如漏写#)或ReferenceError(如在类外访问) - 不能通过
obj.#prop、Reflect.get(obj, '#prop')或for...in访问 - 支持私有 getter/setter,但必须配对使用
#
示例:
class Counter {
#count = 0; // 私有属性,带初始值
#step = 1;
constructor(initial = 0) {
this.#count = initial;
}
increment() {
this.#count += this.#step;
}
get value() {
return this.#count; // 可在公共方法中读取
}
#log() { // 私有方法(见下文)
console.log('current:', this.#count);
}
}
私有方法:用 #name() {} 定义,仅类内可调用
私有方法同样以 # 开头,在类体内定义,可以是普通方法、getter/setter 或生成器(#*name())。它们不能被子类继承(除非子类也定义同名私有方法),也不能被外部或原型链调用。
立即学习“Java免费学习笔记(深入)”;
- 私有方法可访问其他私有字段和私有方法(包括静态私有成员)
- 静态私有方法用
static #methodName() {},只能通过ClassName.#methodName()在类内调用 - 不能用箭头函数声明私有方法(语法不支持)
示例:
class BankAccount {
#balance = 0;
#pin = '1234';
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
this.#logTransaction('deposit', amount); // ✅ 正确:类内调用私有方法
}
}
#logTransaction(type, value) {
console.log(`[${new Date().toISOString()}] ${type}: $${value}`);
}
// 静态私有方法
static #validatePin(pin) {
return typeof pin === 'string' && pin.length === 4;
}
}
注意:私有成员不参与继承与混入
私有字段和方法不会被子类继承。即使子类中定义了同名私有成员,它也是完全独立的;父类方法中访问的 this.#x 永远指向父类定义的私有字段,而非子类的。
- 子类无法覆盖父类私有成员(因为根本不可见)
- 不能在子类中通过
super.#xxx访问父类私有成员(语法错误) - Object.assign、解构、JSON.stringify 等均忽略私有字段
示例:
class Parent {
#id = Math.random();
getId() { return this.#id; }
}
class Child extends Parent {
#id = 'child-id'; // ❌ 这不是覆盖,而是另一个私有字段
// getId() 仍返回父类的 #id,子类无法修改或读取它
}
兼容性与使用建议
目前主流浏览器(Chrome 74+、Firefox 90+、Safari 14.1+)及 Node.js 12.20+/14.6+ 均已支持。构建工具(如 Babel)也提供转译支持(需启用 @babel/plugin-proposal-private-methods 和 @babel/plugin-proposal-class-properties)。
- 优先用
#实现真正私有逻辑,替代下划线约定(_internal)或 WeakMap 模拟 - 避免在私有方法中暴露敏感数据(如直接返回私有引用对象,可能被外部修改)
- 调试时可用
console.dir(instance)查看私有字段(现代 DevTools 支持显示#field,但不可编辑)


















