私有字段必须在constructor中用this.#field = value显式初始化,不可延迟或省略;子类无法访问父类私有字段,需自行声明初始化;初始化值可为参数、表达式或对象,但getter/setter不能替代首次赋值。

私有字段(#)必须在构造函数中通过 this.#field = value 的方式显式初始化,且只能在类的内部访问——不能在构造函数外赋值,也不能在子类中直接访问父类的私有字段。
必须在 constructor 内完成初始化
私有字段不会像普通属性那样自动挂载到实例上,JS 引擎要求你必须在 constructor 中首次赋值,否则会报错 Cannot write to private field。
- ✅ 正确:在
constructor中用this.#name = name - ❌ 错误:在
constructor外定义、或只声明不赋值(如#name;单独一行)、或延迟到其他方法里才赋值
不能在子类中直接访问父类的私有字段
即使子类继承了父类,也无法通过 this.#xxx 访问父类定义的私有字段——它们完全隔离。子类若需类似私有状态,必须自己声明并初始化自己的私有字段。
- 父类中的
#id对子类不可见,子类不能读取、也不能修改 - 子类可声明自己的
#cache,并在自己的constructor中初始化
初始化时可结合参数、默认值或计算逻辑
私有字段的初始值不局限于字面量,可以是参数、解构结果、调用方法的返回值,甚至是一个新对象。
this.#config = { ...defaultConfig, ...options };this.#createdAt = new Date();this.#items = Array.isArray(data) ? [...data] : [];
注意:不能用 getter/setter 绕过初始化限制
即使你为私有字段写了 get #x() 或 set #x(v),也不能代替构造函数中的首次赋值。getter/setter 本身不创建字段,仍需先在 constructor 中完成初始化。
- ❌
get #value() { return this.#_value; }+ 没有this.#_value = ...→ 运行时报错 - ✅ 必须先
this.#_value = initialValue;,之后 getter 才能安全读取











