Class 重點筆記
關於 Class
class 就是構造函數的語法糖,也可以說是構造函數的另一種寫法,使用時直接對 class 調用 new 即可:
class C1 {
constructor(lastName, firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
logName() {
console.log(`My name is ${this.lastName} ${this.firstName}`);
}
}
let c1 = new C1('Peng', 'Jing Jun');
c1.logName(); // My name is Peng Jing Jun
第一次學習 class 時雖然聽過它是構造函數的語法糖,但其實乍看之下還是挺不直覺的,所以這邊解剖一下上述代碼做了些什麼:
首先聲明了一個
C1的class,換成構造函數的寫法就是function C1 () {};class內定義的方法最終都位於原型上,換成構造函數的寫法就是C1.prototype.logName = function () {};constructor方法就是構造函數,內部的this指向被new出來的實體constructor是class的默認方法,通過new關鍵字生成的實體會自動調用constructor方法,即使沒有定義constructor也會默認產生一個空的constructor
console.log(typeof C1); // function
console.log(C1 === C1.prototype.constructor); // true
構造函數的語法糖 class 只是讓原型的寫法更清晰、更像物件導向的語法而已
上述代碼說明了 class 的型別就是函數,而 class 本身就是指向構造函數
注意事項:
class內部定義的方法皆不可枚舉constructor方法默認返回實體物件class與module內部默認以嚴格模式運行,所以不需要再使用use strictclass內部不存在hoistingclass的方法如果內部含有this則默認指向class實體
靜態方法
所有在 class 中定義的方法都會被實體繼承,如果不希望被繼承的話,在方法名前加上 static 關鍵字就表示該方法不會被實體繼承,而且直接通過 class 就可以調用:
class C1 {
static helloWorld() {
console.log('Hello World!');
}
}
C1.helloWorld(); // Hello World!
const c1 = new C1();
c1.helloWorld(); // c1.helloWorld is not a function
上面說明了靜態方法可以直接於 class 上調用,而不是在 class 的實體上調用,如果在實體上調用的話就會噴錯,表示該方法並不存在
另外,父類別的靜態方法可以被子類別繼承:
繼承
JavaScript 類別使用 extends 關鍵字實現單繼承:
class Father {
name;
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Child extends Father {
hello = 'Hello';
}
const res = new Child('Allen Iverson');
console.log(res.name); // Allen Iverson
console.log(res.getName()); // Allen Iverson
console.log(res.hello); // Hello
這段代碼 class Child extends Father {} 使得 Child 繼承 Father 的字段、方法以及構造函數
父類別的構造函數:constructor() 中的 super()
如果想在子類別中調用父類別的構造函數,需要在子類別的構造函數中使用 super() 方法:
class Father {
name;
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Child extends Father {
hello = 'Hello';
constructor(name, str) {
super(name);
this.hello = str;
}
}
const res = new Child('Allen Iverson', 'Changed');
console.log(res.name); // Allen Iverson
console.log(res.getName()); // Allen Iverson
console.log(res.hello); // Changed
上述代碼中在子類別 Child 中的 super(name) 執行了父類別 Father 的構造函數
另外,在子類別構造函數中必須在使用 this 關鍵字之前調用 super() 方法,這樣才能確保父類別的構造函數完成初始化:
class Child extends Father {
hello = 'Hello';
constructor(name, str) {
// ReferenceError ...
this.hello = str;
super(name);
}
}
父類別實體:方法中的 super
class Father {
name;
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Child extends Father {
constructor(name) {
super(name);
}
getName() {
const name = super.getName();
if (name === '') {
console.log('Empty');
} else {
console.log(name);
}
}
}
const res = new Child('');
res.getName(); // Empty
上述代碼中子類別 Child 中的 getName() 透過 super 訪問了父類別 Father 的方法 getName()
另外,也可以在靜態方法中使用 super 訪問父類別的靜態方法