在 2015 年,ECMAScript 6 (ES6) 標準引入了類別。這篇文章將教你如何使用類別。
JavaScript 有一種相對不常見的方式來實現繼承:原型繼承。雖然我認為原型繼承是很好的一種方式,但它與其他流行的程式語言實現的繼承方式不同,後者是基於類別的。
來自於 Java、Python 或其他語言的人很難理解原型繼承的細節,因此 ECMAScript 委員會決定在原型繼承的基礎上添加糖衣語法,使其類似於其他流行語言中基於類別的繼承方式。
重要的是:JavaScript 在底層仍然保持相同,你仍然可以以正常的方式訪問對象原型。
類別定義
以下是一個類別的示例:
class Person {
constructor(name) {
this.name = name
}
hello() {
return 'Hello, I am ' + this.name + '.'
}
}
類別有一個識別符,我們可以使用 new ClassIdentifier()
來創建新對象。
當對象被初始化時,將調用 constructor
方法,並傳入任何參數。
類別可以有任意數量的方法。在這個例子中,hello
是一個方法,可以在所有由這個類別派生的對象上調用:
const flavio = new Person('Flavio')
flavio.hello()
類別繼承
一個類別可以繼承另一個類別,在使用該類別初始化的對象將繼承兩個類別的所有方法。
如果被繼承的類別和繼承的類別中有同樣名稱的方法,最近的方法將優先執行:
class Programmer extends Person {
hello() {
return super.hello() + ' I am a programmer.'
}
}
const flavio = new Programmer('Flavio')
flavio.hello()
(上述程式碼輸出:「Hello, I am Flavio. I am a programmer.」)
類別中並沒有顯式的類別變數聲明,但你必須在構造函數中初始化任何變數。
在類別內部,你可以使用 super()
調用父類。
靜態方法
通常方法是定義在實例上的,而不是定義在類上的。
靜態方法在類上執行:
class Person {
static genericHello() {
return 'Hello'
}
}
Person.genericHello() // Hello
私有方法
JavaScript 沒有內建的方式來定義私有或受保護的方法。
雖然有解決方法,但這裡不會進一步討論。
存取器
你可以添加以 get
或 set
為前綴的方法,來創建一個 getter 和 setter。當你訪問變量時,或者修改其值時,這兩個不同的程式碼塊將被執行。
class Person {
constructor(name) {
this._name = name
}
set name(value) {
this._name = value
}
get name() {
return this._name
}
}
如果只有 getter,該屬性將無法設置,任何對該屬性的設置嘗試(除了在構造函數中初始化該類的新對象時)都將被忽略:
class Person {
constructor(name) {
this._name = name
}
get name() {
return this._name
}
}
如果只有 setter,你可以更改值,但無法從外部訪問:
class Person {
constructor(name) {
this._name = name
}
set name(value) {
this._name = value
}
}
存取器非常有用,當你想在更改屬性值時執行一些代碼,或者當你想創建一個「計算」屬性時。你可以使用 getter 修改返回的值。
你也可以在值更改時運行一些代碼,比如將日誌記錄到控制台或文件中。