ES6 class继承必须在子类constructor中先调super()初始化this,否则报ReferenceError;super还可调父类方法,且ES6自动维护静态和原型链继承关系。
ES6 的 class 语法只是原型继承的语法糖,它本身不改变 JavaScript 继承的本质——所有继承最终都落在 [[Prototype]] 链上。直接用 class + extends 是最简明、最安全的写法,但必须理解 super() 的调用时机和限制。
super()
在子类 constructor 中,this 在调用 super() 前是未初始化的(ReferenceError)。这是 ES6 强制的时序约束,不是可选习惯。
super() 必须在访问 this 之前执行,哪怕只是 console.log(this)
constructor,JS 会自动补一个隐式构造函数并调用 super(...args)
constructor 却没调用 super(),运行时直接报错:ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
class Parent {
constructor(name) {
this.name = name;
}
}
class Child extends Parent {
constructor(name, age) {
// ❌ 错误:不能在 super() 前使用 this
// console.log(this);
super(name); // ✅ 必须第一句(或至少在任何 this 访问前)
this.age = age; // ✅ 此时 this 已就绪
}
}
super 不只是调构造函数,还能调父类方法super 在方法内部指向父类的原型对象(即 Parent.prototype),可用于显式调用被重写的父方法,而不是仅限于构造函数中。
super.methodName() 调用父类同名方法super.staticMethod() 调用父类静态方法super 在箭头函数里不可用(因为箭头函数没有自己的 this 和 super 绑定)class Animal {
speak() {
return "Animal speaks";
}
static type() {
return "Animal";
}
}
class Dog extends Animal {
speak() {
return super.s
peak() + " — woof!"; // ✅ 调用父类实例方法
}
static type() {
return "Dog (" + super.type() + ")"; // ✅ 调用父类静态方法
}
}
ES6 class 继承强制要求子类构造函数通过 super() 初始化 this,而手写原型链(如 Child.prototype = Object.create(Parent.prototype))容易漏掉 constructor 指针修复或忘记在子构造函数里手动调 Parent.call(this, ...)。
Child.__proto__ === Parent(静态继承),传统方式需手动设置Child.prototype.__proto__ === Parent.prototype(原型链继承),传统方式易出错new Parent() 替代 super();手写时若漏掉 Parent.call(this),this 就不会拥有父类实例属性Object.keys() 看不到),传统 prototype 上挂的方法默认可枚举现代浏览器和 Node.js(≥ v6)原生支持 class/extends,Babel 编译后会降级为 function + Object.setPrototypeOf 或 __proto__ 设置,但某些老环境(如 IE)仍需完全避免。
class 语法,得用 Babel + @babel/preset-env 配置目标环境super 调用会被转成 helper 函数(如 _getPrototypeOf),调试时堆栈可能变深super() 的调用位置检查是在编译期强制的真正容易被忽略的是:子类 constructor 中哪怕只写 return {},也必须先调 super();否则不是逻辑错误,而是语法级禁止。