
JavaScript 类继承使用 extends & super
您将学习如何在 ES6 使用 extends 和 super 实现 JavaScript 继承
在本教程中,您将学习如何在 ES6 使用 extends 和 super 实现 JavaScript 继承。
使用 extends 和 super 实现 JavaScript 继承
在 ES6 之前,实现适当的继承需要多个步骤。最常用的策略之一是原型继承。
下面说明了如何使用原型继承技术,使 Bird 继承 Animal 属性:
function Animal(legs) {
this.legs = legs;
}
Animal.prototype.walk = function() {
console.log('walking on ' + this.legs + ' legs');
}
function Bird(legs) {
Animal.call(this, legs);
}
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Animal;
Bird.prototype.fly = function() {
console.log('flying');
}
var pigeon = new Bird(2);
pigeon.walk(); // walking on 2 legs
pigeon.fly(); // flying
ES6 通过使用 extends 和 super 关键词简化了这些步骤。
下面的例子定义 Animal 和 Bird 类,并通过 extends 和 super 关键词建立继承关系。
class Animal {
constructor(legs) {
this.legs = legs;
}
walk() {
console.log('walking on ' + this.legs + ' legs');
}
}
class Bird extends Animal {
constructor(legs) {
super(legs);
}
fly() {
console.log('flying');
}
}
let bird = new Bird(2);
bird.walk();
bird.fly();
代码是如何运行的。
首先,使用 extends 关键词使 Bird 类继承 Animal 类:
class Bird extends Animal { // ...}Animal 类称为基类或父类,而 Bird 类称为派生类或子类。通过 extends 关键词,Bird 类继承 Animal 类的所有方法和属性。
其次,在 Bird 的构造函数调用 super()并使用 legs 参数调用 Animal 的构造函数。
如果子类在有构造函数,JavaScript 在情况下要求调用 super()。正如您在 Bird 类中看到的,这 super(legs) 等同于 ES5 的以下语句:
Animal.call(this, legs);如果 Bird 类没有构造函数,则无需执行任何其他操作:
class Bird extends Animal {
fly() {
console.log('flying');
}
}它等效于以下类声明:
class Bird extends Animal {
constructor(...args) {
super(...args);
}
fly() {
console.log('flying');
}
}但是,子类有一个构造函数,它需要调用 super()。例如,以下代码会导致错误:
class Bird extends Animal {
constructor(legs) {
}
fly() {
console.log('flying');
}
}错误:
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor因为 super() 初始化 this 对象,所以需要在访问 this 对象之前调用 super()。在调用 super() 之前尝试访问 this 也会导致错误。
例如,如果你想初始化 Bird 类的属性 color,你可以这样做:
class Bird extends Animal {
constructor(legs, color) {
super(legs);
this.color = color;
}
fly() {
console.log("flying");
}
getColor() {
return this.color;
}
}
let pegion = new Bird(2, "white");
console.log(pegion.getColor());影子方法
ES6 允许子类和父类有同名的方法。在这种情况下,当你调用子类对象的方法时,子类中的方法会遮蔽父类的方法。
下面的 Dog 类扩展 Animal 类并重新定义 walk() 方法:
class Dog extends Animal {
constructor() {
super(4);
}
walk() {
console.log(`go walking`);
}
}
let bingo = new Dog();
bingo.walk(); // go walking要在子类中调用父类的方法,可以这样调用 super.method(arguments):
class Dog extends Animal {
constructor() {
super(4);
}
walk() {
super.walk();
console.log(`go walking`);
}
}
let bingo = new Dog();
bingo.walk();
// walking on 4 legs
// go walking继承静态成员
除了属性和方法外,子类还继承父类的所有静态属性和方法。例如:
class Animal {
constructor(legs) {
this.legs = legs;
}
walk() {
console.log('walking on ' + this.legs + ' legs');
}
static helloWorld() {
console.log('Hello World');
}
}
class Bird extends Animal {
fly() {
console.log('flying');
}
}在此示例中,Animal 类有静态方法 helloWorld(),并且此方法 Bird.helloWorld() 与 Animal.helloWorld() 方法的行为相同:
Bird.helloWorld(); // Hello World从内置类型继承
JavaScript 允许您通过继承扩展内置类型,例如 Array、 String 、Map 和 Set。
下面 Queue 类扩展引用类型 Array。语法比 Queue 使用构造函数/原型模式实现的要简洁得多。
class Queue extends Array {
enqueue(e) {
super.push(e);
}
dequeue() {
return super.shift();
}
peek() {
return !this.empty() ? this[0] : undefined;
}
empty() {
return this.length === 0;
}
}
var customers = new Queue();
customers.enqueue('A');
customers.enqueue('B');
customers.enqueue('C');
while (!customers.empty()) {
console.log(customers.dequeue());
}结论
- 在 ES6 使用 extends 关键词实现继承。要扩展的类称为基类或父类。扩展基类或父类的类称为派生类或子类。
super(arguments)在子类的构造函数中调用调用父类的构造函数。- 使用
super关键词在子类的方法中调用父类的方法。
















