JavaScript私有字段(#)是语法级硬性限制,子类完全不可见且内存隔离,super无法访问,外部与反射均不可穿透,须通过公有接口协作。

JavaScript 中私有字段(以 # 开头)在子类中完全不可见,这是语言层面的硬性限制,不是作用域或约定问题。
私有字段不参与继承
父类声明的 #field 仅属于该类的实例,子类实例拥有自己独立的 #field(即使同名),二者内存隔离、互不影响。super 关键字无法访问父类私有字段,语法直接报错。
- 子类方法中写 this.#field 指向的是子类自身声明的私有字段,而非父类的
- 未在子类中声明同名 #field 时,this.#field 会触发 ReferenceError
- super.#field 语法非法,引擎解析阶段即拒绝
外部与反射均无法穿透
私有字段对所有外部访问方式彻底隐身:不能通过实例点语法、方括号、Reflect API、Object 方法,甚至 in 操作符都返回 false。
- p.#name → SyntaxError
- p['#name'] 或 Reflect.get(p, '#name') → undefined(实际属性根本不存在)
- Object.getOwnPropertyNames(p)、Object.keys(p) 均不包含任何 # 字段
正确协作方式:靠接口,不靠访问
若子类需读写父类内部状态,父类应主动提供受控的公有或 protected 接口,把封装逻辑留在类内。
立即学习“Java免费学习笔记(深入)”;
- 用 public getter/setter 封装私有字段访问,如 getName() 和 setName()
- 在父类构造函数中接受初始化参数,让子类通过 super(...) 传入定制值
- 避免使用 this._name 这类“约定私有”,它本质是公开的,破坏封装边界
与传统闭包私有的关键区别
# 字段是语法级强制私有,比闭包更严格:闭包可通过返回函数间接暴露,# 字段无任何绕过路径;Symbol 属性仍可被反射获取,# 字段对所有反射 API 完全不可见。
- 闭包变量依赖函数作用域,# 字段依赖类词法作用域
- 每次 new 子类实例,其 # 字段都是全新初始化,与父类实例无关
- TS 的 private 编译后消失,# 是运行时真实约束,不可规避


















