ES6中原生支持了类继承机制。虽然类继承使用的是新语法,但背后依然使用的是原型链。
1.继承基础
ES6中的类支持单继承。使用extends关键字,就可以继承任何拥有constructor和原型的对象。很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数:
1 class Animal {} 2 // 继承类 3 class People extends Animal {} 4 let p = new People() 5 console.log(p instanceof People); // true 6 console.log(p instanceof Animal); // true 7 8 function Vehicle (){} 9 // 继承普通构造函数 10 class Bus extends Vehicle{} 11 let b = new Bus() 12 console.log(b instanceof Bus); // true 13 console.log(b instanceof Vehicle); // true
还可以这么用:
let Bar = class extends Foo {}
2.构造函数、HomeObject和super()
(1)super
派生类的方法可以通过super关键字引用它们的原型。super只能在派生类中使用,而且仅限于类构造函数、实例方法和静态方法内部。
1 class Vehicle { 2 constructor () { 3 this.hasEngine = true 4 } 5 } 6 7 class Bus extends Vehicle { 8 constructor(){ 9 super() // 相当于super.constructor() 10 11 console.log(this instanceof Vehicle); // true 12 console.log(this); // Bus { hasEngine: true } 13 } 14 } 15 16 new Bus()
使用super注意事项:
- 不要在super()之前引用this,否则会抛出 ReferenceError
- super只能在派生类构造函数和静态方法中使用
- 不能单独引用super关键字,要么用它调用构造函数,要么用它引用静态方法
- 调用super会调用父类构造函数,并将返回的实例赋值给this
- super() 的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入
-
1 class Vehicle { 2 constructor(title) { 3 this.title = title 4 } 5 } 6 7 class Bus extends Vehicle { 8 constructor(title) { 9 super(title) 10 } 11 } 12 13 console.log(new Bus('床前明月光')) // Bus {title: "床前明月光"}
-
- 如果没有定义类构造函数,在实例化派生类时会调用super(),且会传入所有传给派生类的参数
-
1 class Vehicle { 2 constructor(title) { 3 this.title = title 4 } 5 } 6 7 class Bus extends Vehicle {} 8 9 console.log(new Bus('床前明月光')) // Bus {title: "床前明月光"}
-
- 如果在派生类追踪显式定义了构造函数,则要么必须在其中调用super(),要么必须在其中返回一个对象。
-
1 class Vehicle {} 2 3 class Car extends Vehicle {} 4 5 class Bus extends Vehicle { 6 constructor () { 7 super() 8 } 9 } 10 11 class Van extends Vehicle { 12 constructor () { 13 return {} 14 } 15 } 16 17 console.log(new Car()); // Car {} 18 console.log(new Bus()); // Bus {} 19 console.log(new Van()); // {}
- 否则将会报如下错误:
-
可以在静态方法中通过super调用继承的类上定义的静态方法:
1 class Vehicle { 2 static identify() { 3 console.log('vehicle'); 4 } 5 } 6 7 class Bus extends Vehicle { 8 static identify(){ 9 super.identify() 10 } 11 } 12 13 Bus.identify() // vehicle
(2)HomeObject
ES6给类构造函数和静态方法添加了内部特性[[HomeObject]],这个特性是一个指针,指向定义该方法的对象。这个指针是自动赋值的。且只能在JavaScript引擎内部访问。super始终会定义为[[HomeObject]]的原型