ES6中的子类和继承
1. 简介
ES6(ECMAScript 2015)引入了一种新的语法,可以实现基于类的继承。这种语法与其他类编程语言相似,如Java、PHP、C++等。使用ES6子类和继承的主要目的是为了避免代码的重复,提高代码的可读性,并提高代码的维护性。
在JavaScript中,类是对象的一种特殊形式,用于描述对象的属性和方法。当我们需要多个对象具有相同的属性和方法时,我们可以创建一个类,然后创建多个该类的实例。
2. 类和实例
在ES6之前,JavaScript没有类的概念。相反,JavaScript使用函数和原型继承来模拟类和继承。
在ES6中,使用class关键字定义类。例如,下面是一个简单的类的定义:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
let a = new Animal('Rabbit');
a.speak(); // 输出 "Rabbit makes a noise."
在上面的代码中,我们定义了一个名为Animal的类。该类有一个构造函数,并且该构造函数有一个名为name的属性。类还有一个名为speak的方法,该方法输出一个字符串。
我们可以使用new关键字创建Animal的实例,如下所示:
let a = new Animal('Rabbit');
a.speak(); // 输出 "Rabbit makes a noise."
在上面的代码中,我们创建了一个名为a的Animal的实例。该实例的名称为Rabbit。我们调用实例的speak方法,并输出一个字符串。
3. 继承
继承是类编程中很重要的一个概念。它使我们可以从现有类派生出新的类,新的类可以继承来自基类的所有属性和方法。
在ES6中,我们可以使用extends关键字来创建一个子类,并继承其父类。例如,下面是一个简单的继承示例:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
console.log(this.name + ' barks.');
}
}
let a = new Dog('Mitzie');
a.speak(); // 输出 "Mitzie barks."
在上面的代码中,我们定义了一个名为Animal的类。该类有一个构造函数,并且该构造函数有一个名为name的属性。类还有一个名为speak的方法,该方法输出一个字符串。
我们接下来定义了一个名为Dog的类,该类使用extends关键字继承自Animal类。我们使用super关键字调用父类的构造函数,并将参数name传递给它。类还有一个名为speak的方法,该方法输出一个不同的字符串。
我们可以使用new关键字创建Dog的实例,如下所示:
let a = new Dog('Mitzie');
a.speak(); // 输出 "Mitzie barks."
在上面的代码中,我们创建了一个名为a的Dog的实例。该实例的名称为Mitzie。我们调用实例的speak方法,并输出一个字符串。
3.1. super关键字
在前面的示例中,我们使用了super关键字。super关键字指向父类的构造函数或方法。在子类的构造函数中调用super关键字将调用父类的构造函数,并将所有参数传递给它。在子类的方法中调用super关键字将调用父类的相应方法。
例如,我们来看一个更复杂的示例:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
super.speak();
console.log(this.name + ' barks.');
}
}
let a = new Dog('Mitzie', 'Collie');
a.speak();
在上面的代码中,我们定义了一个名为Animal的类,以及一个名为Dog的类,它继承自Animal类。该Dog类有一个构造函数,该构造函数调用父类的构造函数。类还有一个名为speak的方法,该方法在调用父类的speak方法后输出一个不同的字符串。
我们可以使用new关键字创建Dog的实例,如下所示:
let a = new Dog('Mitzie', 'Collie');
a.speak();
// 输出:
// Mitzie makes a noise.
// Mitzie barks.
3.2. 继承内置对象
ES6还允许我们继承内置对象。例如,我们可以继承Array对象。
class MyArray extends Array {
get first() {
return this[0];
}
get last() {
return this[this.length - 1];
}
}
let a = new MyArray(1, 2, 3);
console.log(a.first); // 输出 1
console.log(a.last); // 输出 3
在上面的代码中,我们定义了一个名为MyArray的类,它继承自Array类。该类有两个getter方法,分别返回第一个元素和最后一个元素。我们使用new关键字创建一个MyArray对象,并获取其第一个和最后一个元素。
3.3. 继承子类
在ES6中,我们可以继承子类。例如,我们可以定义一个名为Cat的类,它继承自Dog类。
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
console.log(this.name + ' barks.');
}
}
class Cat extends Dog {
speak() {
console.log(this.name + ' meows.');
}
}
let a = new Cat('Fluffy');
a.speak(); // 输出 "Fluffy meows."
在上面的代码中,我们定义了三个类Animal、Dog和Cat。Dog类继承自Animal类,而Cat类继承自Dog类。每个类都有一个名为speak的方法,并输出不同的字符串。
我们可以使用new关键字创建Cat的实例,如下所示:
let a = new Cat('Fluffy');
a.speak(); // 输出 "Fluffy meows."
在上面的代码中,我们创建了一个名为a的Cat的实例。该实例的名称为Fluffy。我们调用实例的speak方法,并输出一个字符串。
3.4. Mixin
Mixin是一种模式,它允许我们将多个类中的属性和方法组合成一个类。在ES6中,我们可以使用类似于继承的语法来实现Mixin。
例如,我们可以定义一个包含两个方法的名为Bipedal的类:
class Bipedal {
walk() {
console.log('walking on two legs');
}
run() {
console.log('running on two legs');
}
}
我们可以通过extends关键字来继承该类来创建一个名为Canine的类:
class Canine extends Bipedal {
bark() {
console.log('barking');
}
}
我们可以通过extends关键字来继承该类来创建一个名为Wolf的类:
class Wolf extends Canine {
howl() {
console.log('howling');
}
}
该示例使用类似于继承的方法来构建mixin。
4. 结论
ES6的类和继承使JavaScript开发人员更容易理解和使用类似于Java、PHP、C++等类编程语言的语法。它使我们能够更好地组织代码,并提高代码的可读性和维护性。使用extends关键字可以轻松地实现继承,而使用super关键字可以方便地调用父类的构造函数和方法。在ES6中,我们还可以继承内置对象,并继承自已有的子类,甚至使用Mixin模式来组合多个类的属性和方法。