子类 constructor 中必须调用 super(),因为 this 在 super() 执行前未初始化,访问会报错;super() 必须首行调用以确保父类完成 this 绑定、原型链设置及 new.target 正确性。

子类 constructor 中必须调用 super(),根本原因在于 JavaScript 的 this 初始化机制——this 在 super() 执行前是未定义的,调用它会直接报错。
为什么 super() 必须放在第一行?
ES6 类继承采用“先继承、后实例化”模型:父类构造函数负责为新对象初始化基础属性和内部状态。子类 constructor 执行时,JS 引擎只创建了一个空对象(由 new 生成),但尚未绑定 this。只有 super() 被调用,父类 constructor 才会接收这个空对象作为 this,并完成属性赋值(比如 this.name = name)、方法挂载等初始化工作。此时 this 才被“激活”,后续才能安全访问或赋值。
- 不调用 super() → this 未初始化 → 访问 this.xxx 报
ReferenceError: Must call super constructor before accessing 'this' - super() 不在首行 → this 已被使用(哪怕只是 console.log(this))→ 同样报错
- 即使父类没有显式 constructor,JS 也会隐式插入
constructor(...args) { super(...args); },所以子类仍需显式调用
super() 不只是执行父类代码
它还承担关键的运行时语义:
- 绑定 new.target:super() 内部执行父类 constructor 时,new.target 指向的是子类(不是父类),这对抽象类校验、动态构造逻辑至关重要
- 维持原型链完整性:super() 触发父类初始化,确保子类实例的 __proto__ 正确指向父类 prototype,从而能沿链访问方法
- 支持多层继承:若父类也继承自更上层类,super() 会逐级向上触发,直到 Object 构造器
super 在 constructor 和普通方法中角色不同
constructor 里的 super() 是函数调用,代表父类构造器;而方法体内的 super.xxx 是对象引用,指向父类原型:
- 在 constructor 中:
super(name)→ 调用父类 constructor,传参并初始化 this - 在实例方法中:
super.speak()→ 从父类 prototype 查找 speak 方法,且 this 仍指向当前子类实例 - 在静态方法中:
super.staticMethod()→ super 指向父类本身(不是 prototype),用于调用父类静态成员
常见错误与规避方式
最容易踩的坑是混淆调用时机和作用域:
- 在箭头函数里用 super → 报错(super 只在 class 方法或 constructor 中有效)
- 把 super 当普通变量打印:
console.log(super)→ 语法错误(super 不是可求值表达式) - 子类没写 constructor 却以为不用 super → 实际 JS 会自动添加空 constructor,但其中仍需 super(),否则 new 实例失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











