類的繼承
class ZxxSubFn extends ZxxFn {
constructor (name, age, salary) {
super(name, age); // 調用父類的構造方法
this.salary = salary
}
// 父類的方法重寫
showName () {
console.log('調用子類的構造方法')
console.log(this.name, this.salary)
}
}
let zxx1 = new ZxxSubFn('zxx', 18, 88888888)
console.log(zxx1) // ZxxSubFn {name: "zxx", age: 18, salary: 88888888}
zxx1.showName() // 調用子類的構造方法 zxx 88888888
重複聲明一個類會引起類型錯誤。
class Foo {};
class Foo {};
// Uncaught TypeError: Identifier 'Foo' has already been declared
若之前使用類表達式定義了一個類,則再次聲明這個類同樣會引起類型錯誤。
let Foo = class {};
class Foo {};
// Uncaught TypeError: Identifier 'Foo' has already been declared
類實質上就是一個函數。類自身指向的就是構造函數。所以可以認爲ES6中的類其實就是構造函數的另外一種寫法!
console.log(typeof ZxxFn); // function
console.log(ZxxFn === ZxxFn.prototype.constructor); // true
子類必須在constructor
方法中調用super
方法,否則新建實例時會報錯。這是因爲子類自己的this
對象,必須先通過父類的構造函數完成塑造,得到與父類同樣的實例屬性和方法,然後再對其進行加工,加上子類自己的實例屬性和方法。如果不調用super
方法,子類就得不到this
對象。
class Point { /* ... */ }
class ColorPoint extends Point {
constructor() {
}
}
let cp = new ColorPoint(); // ReferenceError
如果子類沒有定義constructor
方法,這個方法會被默認添加,代碼如下。也就是說,不管有沒有顯式定義,任何一個子類都有constructor
方法。
class ColorPoint extends Point {
}
// 等同於
class ColorPoint extends Point {
constructor(...args) {
super(...args);
}
}
在子類的構造函數中,只有調用super
之後,纔可以使用this
關鍵字,否則會報錯。這是因爲子類實例的構建,基於父類實例,只有super
方法才能調用父類實例。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
this.color = color; // ReferenceError
super(x, y);
this.color = color; // 正確
}
}
父類的靜態方法,也會被子類繼承。hello()
是A
類的靜態方法,B
繼承A
,也繼承了A
的靜態方法。
class A {
static hello() {
console.log('hello world');
}
}
class B extends A {
}
B.hello() // hello world
Object.getPrototypeOf
方法可以用來從子類上獲取父類。可以使用這個方法判斷,一個類是否繼承了另一個類。
Object.getPrototypeOf(ColorPoint) === Point
// true