1.继承基础
使用extends
关键字,就可以继承任何拥有[[Construct]]
和原型的对象。
class Vehicle {}
let b = new Bus()
b instance of Bus === true
b instance of Vehicle === true
function Person() {}
// 继承构造函数
class Engineer extends Person {}
let e = new Engineer()
e instance of Engineer === true
e instance of 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, Bus {}
Vehicle.identifyClass('vehicle') // vehicle, Vehicle {}
2.构造函数、HomeObject 和 super()
派生类方法可以通过super
关键字引用他们的原型。
super
只能在派生类中使用,且仅限于类构造函数、实例方法和静态方法内部。
在类构造函数中使用super
可以调用父类的构造函数
在静态方法中可以通过super
调用父类的静态方法
class Father {
constructor() {
this.name = 'father'
}
static sayHello() {
console.log('hello)
}
}
class Son extends Father {
constructor() {
// 不要再调用super之前引用this 否则会跑出ReferenceError
super() // 相当于super.contructor()
}
static sayHello() {
super.sayHello()
}
}
Son.sayHello() // hello
ES6 给类构造函数和静态方法添加了内部特性
[[HomeObject]]
,这个特性是一个指针,指向定义该方法的对象。这个指针是自动赋值的而且只能在 Javascript 引擎内部访问。super 始终会定义为[[HomeObject]]
的原型
使用super
时的注意事项
- super 只能在派生类构造函数(
constructor
)和静态方法中使用 - 不能单独引用
super
,要么调用构造函数,要么用它引用静态方法 - 调用
super()
会调用父类构造函数,并将返回的实例赋值给 this super()
的行为如同调用构造函数,如果需要传参则需要手动传入- 如果没有定义类构造函数,在实例化派生类时会调用
super()
,而且会传入所有传给派生类的参数 - 在类构造函数中,不能在调用
super()
之前引用 this - 如果在派生类中显示定义了构造函数,则要么调用
super()
,要么在其中返回一个对象
class Father {}
class Son extends Father {
constructor() {
// super()
return {}
}
}
3.抽象基类
定义:可供其他类继承,但本身不会被实例化
实现:通过new.target
,在实例化是检测是不是抽象基类,阻值对抽象基类的实例化
另:通过在抽象基类构造函数中进行检查,可以要求派生类必须定义某个方法。因为原型方法在调用类构造函数之前就已经存在了,所以可以通过 this 来检查
class Father {
constructor() {
console.log(new.target)
if(new.target === Father) {
throw new Error('Father不能实例化')
}
if(!this.foo) {
throw new Error('继承类必须定义foo()')
}
}
}
class Son extneds Father {}
new Son() // Error: 继承类必须定义foo()