js中class是带约束的原型语法糖,需严守声明顺序(静态→构造器→字段→方法),constructor仅做必要初始化,继承必调super()且仅一次,私有字段#xxx须顶层声明且真私有。

JS 中 class 语法不是“更高级的函数”,而是带约束的原型语法糖。写得不规范,轻则 constructor 指向错、私有字段报错、继承链断裂,重则在低版本环境直接运行失败。防坑关键不在记住所有规则,而在理解哪些地方 JS 会“悄悄干预”你的代码。
class 声明顺序不能乱:静态 → 构造器 → 字段 → 方法
类内部没有强制顺序,但混乱排列会让协作和维护成本陡增。推荐结构如下:
- 最顶部放 static 字段和方法(如
static VERSION = '2.1'、static fromJSON()),它们不依赖实例,应最先被看到 - 紧接着是 constructor,只做必要初始化(赋值、校验、绑定),不发请求、不操作 DOM
- 然后是 实例字段声明(
count = 0、#id = Math.random()),包括公有和私有字段,统一显式写出 - 最后是 方法区,按调用频次和语义分组:生命周期方法(
init()、destroy())→ 核心业务方法(save()、validate())→ 辅助方法(_format()或#_parse())→ getter/setter
constructor 不是万能初始化入口,别在里面干脏活
很多人习惯把所有初始化逻辑塞进 constructor,但这是高危操作:
- constructor 中调用异步方法(
fetch、await)会导致实例创建后状态不可知,且无法await new MyClass() - 参数校验应尽早失败,但复杂校验建议抽成独立方法(如
this._checkConfig(config)),避免 constructor 过长 - 不要在 constructor 里给 this 绑定事件或监听器,这类副作用更适合放在
init()等显式生命周期方法中 - 若需默认值,优先用字段声明(
timeout = 5000),而非在 constructor 里写this.timeout = options.timeout ?? 5000
继承时 super() 必须在 this 之前,且只能调用一次
ES6 继承强制要求子类 constructor 中第一句必须是 super(),否则报 ReferenceError: Must call super constructor:
-
super()等价于Parent.call(this, ...args),它负责初始化父类实例属性并建立this上下文 - 在
super()之前访问this会直接报错;在super()之后再调用一次,不会报错但会造成父类逻辑重复执行(如重复创建数组、重复注册监听) - 如果父类 constructor 接收参数,子类必须显式传入:
super(name, age),不能省略或只传部分 - 注意:super 不仅用于 constructor,在子类方法中也可用
super.method()调用父类同名方法,但不能在箭头函数或静态方法中使用
私有字段 #xxx 是真私有,但声明即强制存在
私有字段(#name、#_cache)由语言级保障,外部无法访问或枚举,但也带来两个硬性约束:
- 必须在类顶层声明(哪怕初始值为
undefined),不能只在 constructor 或方法里动态添加:this.#id = 123前必须有#id;或#id = null; - 私有字段无法被 JSON.stringify 序列化,也无法通过
Object.keys()、for...in遍历,调试时容易误判“字段没生效” - 私有方法同样需以
#开头定义,且只能在类内部通过this.#method()调用,不能用字符串反射(this['#method']无效) - 注意:私有字段名区分大小写,
#Data和#data是两个不同字段











