在 ES6 的 class
中,super
关键字的行为在 构造函数 和 非构造函数(普通方法) 中有显著区别,主要体现在以下方面:
1. 构造函数中的 super
行为规则
必须显式调用:
在子类的构造函数中,必须先调用super()
,才能使用this
。否则会抛出错误:class Child extends Parent { constructor() { this.name = "Alice"; // ❌ 错误:Must call super constructor in derived class super(); } }
super
作为函数调用:
super()
的作用是调用父类的构造函数,并初始化子类实例的this
。- 参数需传递给父类构造函数。
- 相当于
Parent.prototype.constructor.call(this, ...args)
。
调用顺序:
super()
必须位于构造函数的最顶部(在访问this
之前)。
示例
class Parent {
constructor(name) {
this.name = name;
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // ✅ 必须先调用 super()
this.age = age;
}
}
const child = new Child("Alice", 10);
console.log(child.name); // "Alice"
console.log(child.age); // 10
2. 非构造函数中的 super
(普通方法)
行为规则
super
作为对象使用:
在普通方法中,super
指向 父类原型(Parent.prototype),用于调用父类方法。super.method()
等价于Parent.prototype.method.call(this)
。
可调用父类原型方法:
通过super
可以访问父类原型上定义的方法,但无法直接访问父类实例属性。无需强制调用顺序:
可以在方法内任意位置使用super
,无需在访问this
之前调用。
示例
class Parent {
sayHello() {
console.log("Hello from Parent");
}
}
class Child extends Parent {
sayHello() {
super.sayHello(); // ✅ 调用父类方法
console.log("Hello from Child");
}
}
const child = new Child();
child.sayHello();
// 输出:
// "Hello from Parent"
// "Hello from Child"
关键区别总结
特性 | 构造函数中的 super |
非构造函数中的 super |
---|---|---|
调用形式 | 必须作为函数调用(super() ) |
作为对象调用(super.method() ) |
必要性 | 必须显式调用,否则报错 | 可选调用(根据需要) |
作用 | 初始化 this ,继承父类实例属性 |
调用父类原型方法 |
访问 this 的时机 |
必须在 super() 调用之后 |
可直接使用 this (无需前置条件) |
静态方法中的行为 | 无(静态方法无构造函数) | super 指向父类(而非父类原型) |
静态方法中的 super
在静态方法中,super
指向 父类本身,而非父类原型:
class Parent {
static staticMethod() {
console.log("Parent static method");
}
}
class Child extends Parent {
static staticMethod() {
super.staticMethod(); // 调用父类的静态方法
console.log("Child static method");
}
}
Child.staticMethod();
// 输出:
// "Parent static method"
// "Child static method"
常见错误场景
1. 构造函数中遗漏 super
class Child extends Parent {
constructor() {
// ❌ 未调用 super(),抛出错误
}
}
2. 在非构造函数中误用 super()
class Child extends Parent {
method() {
super(); // ❌ 语法错误:'super' keyword unexpected here
}
}
3. 错误访问父类实例属性
class Parent {
constructor() {
this.value = 42;
}
}
class Child extends Parent {
getValue() {
return super.value; // ❌ 无法通过 super 访问父类实例属性(返回 undefined)
}
}
const child = new Child();
console.log(child.getValue()); // undefined
总结
- 构造函数中的
super
:
强制调用,用于初始化this
,确保父类实例属性正确继承。 - 非构造函数中的
super
:
用于调用父类原型方法,无需强制顺序,但需注意super
的指向。 - 静态方法中的
super
:
指向父类本身,用于调用父类静态方法。