必须在子类构造函数首行调用super(),否则this未初始化会报错;super()负责初始化实例结构、设置原型链并激活this绑定;省心做法是不写constructor,由引擎自动插入默认实现。

直接在子类构造函数第一行写 super(),就解决了。这不是可选项,是 JavaScript 强制要求——只要写了 constructor,就必须首行调用 super(),否则 this 根本不可用,连 console.log(this) 都会立刻报错。
为什么必须首行调用 super()
super() 不只是“执行父类逻辑”,它实际做了三件事:
- 初始化子类实例的内部结构(比如 [[Prototype]] 槽位)
- 把子类实例的原型链正确指向父类原型
- 正式激活
this绑定,让后续对this.xxx的读写成为可能
没调 super() 前,this 处于“未初始化”状态,任何访问都会触发 ReferenceError: Must call super constructor in derived class before accessing 'this'。
常见错误写法及修正
以下写法全都会报错,哪怕构造函数看起来“什么都没做”:
-
constructor() { }→ 缺少super() -
constructor() { this.name = 'x'; super(); }→this在super()前被使用 -
constructor() { return; super(); }→return提前终止,super()根本没执行
正确写法只有一种模式:super() 必须是第一条可执行语句(注释和变量声明不算):
- 无参:
constructor() { super(); } - 传参:
constructor(name) { super(name); this.name = name; }(自身属性赋值放super()后)
不想手动处理?那就别写 constructor
如果子类不需要定制初始化逻辑,最省心的做法是:完全不定义 constructor。
JavaScript 引擎会自动插入默认构造函数:constructor(...args) { super(...args); },既安全又无需操心。
一旦你显式写了 constructor,就意味着你要接管整个初始化流程——而 super() 就是你向父类移交控制权的第一步,没有例外。
异步场景怎么办?别在构造函数里搞异步
构造函数必须同步执行,super() 不能放在 await、setTimeout 或 if 分支里——这些写法在语法解析阶段就会被拒绝。
正确做法是改用工厂函数:
- 先异步获取数据
- 再同步调用
new Child(data),让super(data)在构造函数内自然执行

















