JavaScript高级程序设计(一)继承

386 阅读3分钟

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

前言:

ES6 类支持单继承。使用 extends 关键字,就可以继承任何拥有[[Construct]]和原型的对象。 很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数(保持向后兼容):

1.继承基础

继承类

class Vehicle {}  
class Bus extends Vehicle {}  

let b = new Bus();  

console.log(b instanceof Bus); // true  

console.log(b instanceof Vehicle); // true  

function Person() {}  

继承普通构造函数

class Engineer extends Person {}  

let e = new Engineer();  

console.log(e instanceof Engineer); // true  

console.log(e instanceof Person); // true 

派生类都会通过原型链访问到类和原型上定义的方法。this 的值会反映调用相应方法的实例或者类:

class Vehicle {  

 identifyPrototype(id) {  
 console.log(id, this);  
 } 
 static identifyClass(id) {  
 console.log(id, this);  
 }  
}  

class Bus extends Vehicle {}  
let v = new Vehicle();  
let b = new Bus();  
b.identifyPrototype('bus'); // bus, Bus {}  
v.identifyPrototype('vehicle'); // vehicle, Vehicle {}  
Bus.identifyClass('bus'); // bus, class Bus {}  
Vehicle.identifyClass('vehicle'); // vehicle, class Vehicle {}  

注意: extends 关键字也可以在类表达式中使用,因此 let Bar = class extends Foo {}

是有效的语法。

2. 构造函数、HomeObjectsuper()

派生类的方法可以通过 super 关键字引用它们的原型。这个关键字只能在派生类中使用,而且仅 限于类构造函数、实例方法和静态方法内部。在类构造函数中使用 super 可以调用父类构造函数。

class Vehicle {  
 constructor() {  
 this.hasEngine = true;  
 }  
}  
class Bus extends Vehicle {  
 constructor() {  

不要在调用 super()之前引用 this,否则会抛出 ReferenceError

 super(); // 相当于 super.constructor()  

 console.log(this instanceof Vehicle); // true  

 console.log(this); // Bus { hasEngine: true }  
 }  
}  
new Bus();  

在静态方法中可以通过 super 调用继承的类上定义的静态方法:

class Vehicle {  
 static identify() {  
 console.log('vehicle');  
 }  
}  
class Bus extends Vehicle {  
 static identify() {  
 super.identify();  
 }  
}  

Bus.identify(); // vehicle  

注意: ES6 给类构造函数和静态方法添加了内部特性[[HomeObject]],这个特性是一个 指针,指向定义该方法的对象。这个指针是自动赋值的,而且只能在 JavaScript 引擎内部 访问。super 始终会定义为[[HomeObject]]的原型。 在使用 super 时要注意几个问题。 super 只能在派生类构造函数和静态方法中使用。

class Vehicle {  

 constructor() {  

 super();  

 // SyntaxError: 'super' keyword unexpected  

 }  

}  

不能单独引用 super 关键字,要么用它调用构造函数,要么用它引用静态方法。

class Vehicle {}  
class Bus extends Vehicle {  
 constructor() {  
 console.log(super);  
 // SyntaxError: 'super' keyword unexpected here  
 }  

}  

 调用 super()会调用父类构造函数,并将返回的实例赋值给 this。

class Vehicle {}  
class Bus extends Vehicle {  
 constructor() {  
 super();  
 console.log(this instanceof Vehicle);  
 }  
}  
new Bus(); // true  

super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入。

class Vehicle {  
 constructor(licensePlate) {  
 this.licensePlate = licensePlate;  
 }  
}  
class Bus extends Vehicle {  
 constructor(licensePlate) {  
 super(licensePlate);  
 }  
}  
console.log(new Bus('1337H4X')); // Bus { licensePlate: '1337H4X' }  

如果没有定义类构造函数,在实例化派生类时会调用 super(),而且会传入所有传给派生类的

class Vehicle {  
 constructor(licensePlate) {  
 this.licensePlate = licensePlate;  
 }  
}  
class Bus extends Vehicle {}  
console.log(new Bus('1337H4X')); // Bus { licensePlate: '1337H4X' }  

在类构造函数中,不能在调用 super()之前引用 this。

class Vehicle {}  
class Bus extends Vehicle {  
 constructor() {  
 console.log(this);  
 }  
}  
new Bus();  
// ReferenceError: Must call super constructor in derived class  
// before accessing 'this' or returning from derived constructor  

如果在派生类中显式定义了构造函数,则要么必须在其中调用 super(),要么必须在其中返回 一个对象。

class Vehicle {}  
class Car extends Vehicle {}  
class Bus extends Vehicle {  
 constructor() {  
 super();  
 }  
}  
class Van extends Vehicle {  
 constructor() {  
 return {};  
 }  
}  
console.log(new Car()); // Car {}  
console.log(new Bus()); // Bus {}  
console.log(new Van()); // {}  

总结

以上就是今天的JavaScript高级程序设计(一)继承
会持续更新中…
原创不易,期待您的点赞关注与转发评论😜😜