JavaScript 中可通过 # 前缀定义真正的私有属性和方法,自 ES13(2022)起原生支持;# 字段仅限 class 内部访问,支持实例/静态私有字段与方法,但不支持私有 accessor,子类不可访问父类私有成员。

JavaScript 中可以通过 # 前缀(即哈希符号)在 class 内定义真正的私有属性和私有方法,这是 ECMAScript 2022(ES13)正式标准化的语法,原生支持、无需编译或模拟。
使用 # 定义私有属性
在 class 中以 # 开头的标识符即为私有字段,只能在 class 内部访问,外部读写都会报 TypeError:
- 必须在 class 主体中声明(可在构造函数前或后),不能动态添加
- 支持公有/私有实例字段、私有静态字段(
static #name) - 不能在 class 外通过
obj.#prop访问,也不能用in、Reflect.ownKeys()或解构检测
示例:
class Counter {
#count = 0; // 私有实例字段
static #step = 1; // 私有静态字段
<p>increment() {
this.#count += Counter.#step;
}</p><p>getCount() {
return this.#count;
}
}使用 # 定义私有方法
私有方法同样以 # 开头,可为实例方法或静态方法,仅能在 class 内部调用:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 私有实例方法:用
#methodName()声明,内部通过this.#methodName()调用 - 私有静态方法:用
static #methodName()声明,内部通过ClassName.#methodName()或this.constructor.#methodName()调用 - 不支持私有 getter/setter 的简写形式(如
get #value()是语法错误),但可用完整方法模拟
示例:
class BankAccount {
#balance = 0;
<h1>validateAmount(amount) {</h1><pre class="brush:php;toolbar:false;">if (typeof amount !== 'number' || amount < 0) {
throw new Error('Invalid amount');
}}
deposit(amount) { this.#validateAmount(amount); this.#balance += amount; }
getBalance() { return this.#balance; } }
注意事项与常见误区
虽然 # 语法简洁明确,但需注意以下限制:
- 私有成员名是“词法绑定”的,
#name和#name在不同 class 中互不影响(不存在命名冲突) - 无法在子类中直接访问父类的私有成员(
super.#method()不合法),这是有意设计,确保封装性 - 暂不支持私有 accessors(
#get #prop()等语法无效),如需私有访问逻辑,改用私有方法 + 公有 getter - Babel、TypeScript 等工具对私有字段的支持需开启对应目标环境(如
target: "es2022"),否则会降级为 WeakMap 模拟(不完全等价)
替代方案(不推荐用于新项目)
在 # 语法普及前,常用 WeakMap 或闭包模拟私有,但存在缺陷:
- WeakMap 方式需额外维护映射表,代码冗长,且无法阻止反射(
WeakMap.prototype.has可被探测) - 闭包方式(如在构造函数内定义变量和函数)无法实现真正共享的私有静态成员
- 下划线约定(如
_internal)纯属命名提示,无任何语言级保护
现代浏览器和 Node.js(v16.0+ 默认启用,v12.20+ 可通过 flag 启用)均已稳定支持 # 语法,应作为首选。

















