JavaScript/OOP-類
面向物件程式設計中基於類的程式語言的流行程度激勵了 JavaScript 社群,他們用模仿基於類的程式設計方法的語法來覆蓋其基於原型的 OOP 實現。EcmaScript 2015 (ES6) 透過相應的關鍵詞(如“class”或“extend”)得到了擴充套件。
類是用於建立物件的模板或“藍圖”。它們封裝了它們的資料,幷包含用於處理資料的函式。
class Person {
// Class body is always implicitly in "use strict" mode
constructor(name) {
// Data. Declarations like 'let x = 0' are not necessary.
this.name = name;
}
// functionality
showName() {
return "My name is: " + this.name;
}
}
const ada = new Person("Lovelace");
alert(ada.showName());
關鍵字 class 引入類定義。在示例中,Person 是類名。它後面跟著用花括號 { }(第 1 行到第 11 行)括起來的類主體。在主體內部,有一個特殊方法 constructor。此函式在類建立期間被呼叫。在示例中,它接受一個引數,即一個人的姓名。在 constructor 內部,此引數使用關鍵字“this”在內部儲存。該類只提供一個功能:showName 方法。
上面的語法顯示瞭如何處理單個物件(例項 - 就像上面示例中的“ada”)的屬性和方法。還可以定義在單個物件級別不可用但在類級別可用的屬性和方法 - 上述示例中的“Person”。它們由關鍵字 static 引入。
class Person {
constructor(name) {
// data
this.name = name;
}
static className = "The PERSON Class";
static showClassName() {return "The name of this class is: " + this.className};
showName() {
return "My name is: " + this.name;
}
}
const ada = new Person("Lovelace");
// alert(ada.showClassName()); // Error!
alert(Person.showClassName());
第 7 行和第 8 行使用“static”關鍵字。因此,屬性和方法不適用於例項,而只適用於整個類。
類方法可以作為屬性提供。這使程式設計師能夠區分透過圓括號 () 訪問方法和屬性。關鍵字 get 引入此功能。
class Person {
constructor(name) {
this.name = name;
}
// getter
get showTheName() {
return this.showName();
}
// 'regular' method
showName() {
return "My name is: " + this.name;
}
}
const ada = new Person("Lovelace");
// NO parenthesis ()
alert(ada.showTheName);
接下來,我們定義一個類層次結構。這是使用關鍵字 extends 完成的。在示例中,Employee 是 Person 的子類,並且可以訪問其所有屬性和方法。
class Person {
constructor(name) {
this.name = name;
}
// method
showName() {
return "My name is: " + this.name;
}
}
class Employee extends Person {
constructor(name, company) {
super(name);
this.company = company;
}
// method
showCompany() {
return "I, " + this.name + ", work at the company " + this.company;
}
}
const henry = new Employee("Henry Miller", "ACME Inc.");
alert(henry.showCompany());
alert(henry.showName()); // method of the parent class
第 12 行呼叫父類的建構函式。這是必要的,因為父類的 constructor 建立“this”。
預設情況下,類屬性和方法是可訪問的。您可以使用井號 # 作為它們名稱的第一個字元來隱藏它們。
class Person {
// two hidden properties (sometimes called 'private fields')
#firstName;
#lastName;
constructor(firstName, lastName) {
this.#firstName = firstName;
this.#lastName = lastName;
// one public property
this.name = lastName + ", " + firstName;
}
#showName() { // hidden method
alert("My name is " + this.name);
}
}
const ada = new Person("Ada", "Lovelace");
alert(ada.name); // ok
alert(ada.firstName); // undefined
alert(ada.#firstName); // undeclared private field
alert(ada.#showName()); // undeclared private method
如果方法名在“父”類和“子”類中都被使用,JavaScript 引擎將呼叫相關類的那個方法。
class Person {
constructor(name) {
this.name = name;
}
// method name is used also in 'child'
showName() {
return "My name is: " + this.name;
}
}
class Employee extends Person {
constructor(name, company) {
super(name);
this.company = company;
}
// same method name as in 'parent'
showName() {
return "My name is: " + this.name + ". I'm working at the company " + this.company;
}
}
const henry = new Employee("Henry Miller", "ACME Inc.");
alert(henry.showName()); // from Employee
const nextPerson = new Person("John");
alert(nextPerson.showName()); // from Person
示例定義並使用兩個不同的方法 showName。
this 不是變數或物件;它是一個關鍵字。根據上下文,它指的是不同的東西。在類定義的上下文中,它指的是類本身,例如,this.city = "Nairobi" 指的是當前類的屬性“city”。
當 this 在檔案的最頂層使用時(換句話說,在任何函式或物件之外),它指的是全域性物件。在嚴格模式下,在函式中,this 為 undefined。在 DOM 事件中,它指的是接收事件的元素。