JavaScript自2022年起支持以#开头的原生私有字段和方法,仅限类内访问,声明需在类体中显式写出,不可被外部访问或反射API捕获,须配合getter/setter提供受控公有接口。

用 # 号声明私有字段和私有方法
ES2022(ES13)起,JavaScript 正式支持原生私有成员,语法统一且强制:所有私有字段和方法都必须以 # 开头,且只能在类定义内部访问。
声明时需注意两点:一是必须在类体中显式声明(如 #name; 或 #name = 'default';),二是在 constructor 或其他方法中使用时,必须先声明再访问,否则报错。
- 私有字段示例:
class User { #id; #token; constructor(id, token) { this.#id = id; this.#token = token; } } - 私有方法示例:
#validate() { return this.#token?.length > 8; },只能被this.#validate()在类内调用 - 外部访问
user.#id或user.#validate()会立即抛出SyntaxError,不是运行时报错,而是解析阶段就被阻止
私有成员不能出现在实例属性列表中
私有字段不属于对象的可枚举或自有属性,因此不会被常规反射 API 捕获。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Object.keys(user)、Object.getOwnPropertyNames(user)都只返回公有属性(如name),不包含任何#xxx -
JSON.stringify(user)完全忽略私有字段,序列化结果里看不到它们 -
user['#id']或user[#id]均为undefined,无法通过方括号语法动态访问
配合 getter/setter 控制公有接口
私有字段本身不可见,但可通过公有访问器提供受控读写能力。这是封装的核心实践。
立即学习“Java免费学习笔记(深入)”;
- 在 getter 中可添加逻辑,比如格式化:
get displayName() { return `User:${this.#name.toUpperCase()}`; } - 在 setter 中可校验输入:
set age(value) { if (value > 0 && value - 务必用不同名的私有字段存储真实值(如
#age),避免在 setter 里写this.age = value导致无限递归
不推荐用下划线约定替代真正的私有
像 _name 这类命名只是开发者间的“君子协定”,没有任何语言级保护,外部仍可自由读写、误删或覆盖。
- 调试时容易混淆哪些是真私有、哪些只是习惯命名
- IDE 和 TypeScript 无法据此提供准确提示或类型检查
- 团队协作中缺乏约束力,维护成本高

















