推荐答案
super 关键字在 ES6 中主要有两个作用,且都与类的继承相关:
在子类的构造函数中使用
super():super()用于调用父类的构造函数。必须在子类的构造函数中使用this关键字之前调用super()。这是因为this关键字需要在父类构造函数执行后才能正确初始化。super()可以接受参数,这些参数会传递给父类的构造函数。
在子类的方法中使用
super.methodName():super.methodName()用于调用父类中定义的方法。这允许子类在继承父类方法的基础上进行扩展或修改。- 可以用来访问父类中被子类方法覆盖的方法。
本题详细解读
继承与 super 的必要性
在 ES6 中,通过 class 关键字可以定义类,并且可以使用 extends 关键字实现类的继承。当一个子类继承父类时,子类会继承父类的属性和方法。但是,子类也需要有自己的构造逻辑,以及可能需要修改或扩展父类的方法。这就是 super 关键字存在的意义。
super() 的作用和用法
当子类需要自己的构造逻辑时,我们必须在子类的构造函数中使用 super() 来调用父类的构造函数。super() 的主要作用是:
- 初始化
this: 在 ES6 的类继承中,子类构造函数必须先执行父类构造函数,这样才能正确地初始化this对象。如果没有调用super(),则尝试使用this会抛出错误。 - 继承父类属性:
super()会执行父类的构造函数,这意味着子类可以继承父类在构造函数中初始化的属性。
示例:
// www.javascriptcn.com code example
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log('Generic animal sound');
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类的构造函数
this.breed = breed;
}
bark() {
console.log('Woof!');
}
}
const myDog = new Dog('Buddy', 'Labrador');
console.log(myDog.name); // 输出: Buddy
console.log(myDog.breed); // 输出: Labrador
myDog.speak(); // 输出: Generic animal sound
myDog.bark(); // 输出: Woof!在上面的示例中,Dog 继承了 Animal。 Dog 类的构造函数中使用了 super(name) 来调用父类 Animal 的构造函数,并传递了 name 参数。这确保了 Dog 实例也具有 name 属性。
super.methodName() 的作用和用法
当子类需要调用父类的方法时,可以使用 super.methodName()。这通常发生在以下两种情况:
- 扩展父类方法: 子类可以在调用父类方法的基础上添加额外的逻辑。
- 覆盖父类方法: 子类可以完全覆盖父类方法,如果仍然需要使用父类的方法,可以使用
super.methodName()来调用。
示例:
// www.javascriptcn.com code example
class Animal {
speak() {
console.log('Generic animal sound');
}
}
class Dog extends Animal {
speak() {
super.speak(); // 调用父类的 speak 方法
console.log('Woof!'); // 添加额外的逻辑
}
}
const myDog = new Dog();
myDog.speak(); // 输出: Generic animal sound \n Woof!在这个示例中,Dog 类覆盖了父类 Animal 的 speak 方法。但是,在 Dog 的 speak 方法内部,使用了 super.speak() 来调用父类的 speak 方法,然后又添加了 console.log('Woof!'); 语句,从而扩展了 speak 方法的功能。
注意事项
- 必须在
this之前调用super(): 在子类构造函数中,必须在访问this之前调用super()。否则,会抛出错误。 - 只在构造函数和方法中使用:
super只能在子类的构造函数和方法中使用。在其他地方使用super会导致错误。 super的上下文:super的上下文始终是当前子类的实例。