在上篇因為 JavaScript 沒有原生的 Class,所以他的繼承方式是以 prototype (原型),在 ES6 中引入了 Class(類別)語法,他是一種語法糖,提供了更容易使用的方式來建立和管理物件以及實現物件導向程式(OOP)的概念。這種語法糖使得在 JavaScript 中建立和使用類型更加直觀和類似傳統的類型語言(如 Java 或 C++ )。
在 ES5 中,雖然沒有像 ES6 中的 Class 語法那樣的類別概念,但我們可以使用 Constructor function(建構式函式)和 Prototype(原型)來實現類似的物件和繼承模式。
function Food(name, type) {
this.name = name;
this.type = type;
}
// 在食物的原型上添加一個方法
Food.prototype.describe = function() {
console.log(`This is ${this.name}, it is a type of ${this.type} food.`);
};
// 創建食物的實例
const pizza = new Food("Pizza", "Italian");
const sushi = new Food("Sushi", "Japanese");
// 使用食物的方法
pizza.describe(); // This is Pizza, it is a type of Italian food.
sushi.describe(); // This is Sushi, it is a type of Japanese food.
我們藉由以上的例子,複習一下當時透過 Constructor function(建構式函式)和 Prototype(原型)來實現類似的物件和繼承模式,這邊也可以回頭看看:Day 11 - 理解 JavaScript,為什麼要知道原型、原型鏈與原型繼承?
我們將上方例子轉換為 ES6 的 Class 語法:
class Food {
constructor(name, type) {
this.name = name;
this.type = type;
}
describe() {
console.log(`This is ${this.name}, it is a type of ${this.type} food.`);
}
}
// 同樣也使用 new 關鍵字來建立類別的實例
const pizza = new Food("Pizza", "Italian");
const sushi = new Food("Sushi", "Japanese");
pizza.describe(); // This is Pizza, it is a type of Italian food.
sushi.describe(); // This is Sushi, it is a type of Japanese food.
整理一下 ES5 與 ES6 之間的差異:
類別定義方式:
ES5 使用Constructor function(建構式函式)來建立類別,
而 ES6 使用 class 關鍵字來定義類別。
建構式函式與初始化:
ES5 在建構子內部使用 this 來初始化屬性,
而 ES6 使用 constructor 方法來初始化物件的屬性。
方法定義:
在 ES5 中,方法定義通常發生在原型物件上,使用 prototype。
在 ES6 中,方法直接在類別內部使用函數定義,不需要 prototype。
我們已經看到如何使用 ES6 的 Class 語法來定義和創建一個簡單的 Food
類別,以及如何建立食物的實例。
接著,我們將繼續探討 ES6 中的類別繼承概念:
class Food {
constructor(name, type) {
this.name = name;
this.type = type;
}
describe() {
console.log(`This is ${this.name}, it is a type of ${this.type} food.`);
}
}
class Dessert extends Food {
constructor(name, type, flavor) {
super(name, type); // 使用 super 來調用父類別的建構子
this.flavor = flavor;
}
describe() {
console.log(`This is ${this.name}, it is a type of ${this.type} food with a ${this.flavor} flavor.`);
}
enjoy() {
console.log(`Enjoy your ${this.flavor} ${this.name}!`);
}
}
const cake = new Dessert("Cake", "Dessert", "chocolate");
cake.describe(); // This is Cake, it is a type of Dessert food with a chocolate flavor.
cake.enjoy(); // Enjoy your chocolate Cake!
在以上例子中,將繼承應用到了 Food
類別,並創建了一個 Dessert
類別(Food
的子類別)。
可以發覺我們通過 extends
關鍵字建立一個子類別,並使用 super
關鍵字調用父類別的建構子。
Dessert
類別繼承了 Food
類別,他擁有 Food
的屬性和方法,包括 name
和 type
屬性以及 describe
方法。Dessert
的建構子中,我們使用 super(name, type)
調用了父類別 Food
的建構子,以確保屬性正確初始化。Dessert
類別還有自己的 describe
方法,用於描述食物的名稱、類型和口味。enjoy
方法,用於特定於甜點的行為。最後,我們建立一個 cake
實例,並使用 describe
和 enjoy
方法來展示繼承和子類別獨有的功能。
我們已經探討了如何使用 ES6 的 Class 語法來定義類別,以及如何使用繼承來建立類別之間的層次結構。
現在,我想介紹 ES6 中的類別靜態方法的概念。
靜態方法是與類別本身相關聯的方法,而不是與類別的實例相關聯,他用於執行與整個類別相關的操作。
如果希望做到某個專屬於這個原型的方法,在 ES6 中,你可以使用 static
關鍵字來定義靜態方法。
繼續銜接上面的 Food
來說明類別靜態方法的使用:
class Food {
constructor(name, type) {
this.name = name;
this.type = type;
}
describe() {
console.log(`This is ${this.name}, it is a type of ${this.type} food.`);
}
static isHealthy(food) {
// 靜態方法,判斷一個食物是否健康
return food.type === "Healthy";
}
}
const salad = new Food("Salad", "Healthy");
const pizza = new Food("Pizza", "Italian");
salad.describe(); // This is Salad, it is a type of Healthy food.
pizza.describe(); // This is Pizza, it is a type of Italian food.
console.log(Food.isHealthy(salad)); // true,沙拉是健康食物
console.log(Food.isHealthy(pizza)); // false,比薩不是健康食物
在 Food
類別中定義了一個靜態方法 isHealthy
,該方法接受一個食物對象作為參數,並判斷該食物是否屬於健康食物。這個靜態方法不需要 Food
類別的實例,而是可以直接通過 Food.isHealthy()
調用。
我們建立了兩個不同類型的食物(沙拉和比薩),並使用 describe
方法。
然後,使用 Food.isHealthy()
靜態方法來判斷這些食物是否健康。
ES6 中的 Class 語法為 JavaScript 引入更接近傳統物件導向程式設計的方式,使得在 JavaScript 中建立和管理物件更加直觀且容易。今天分享 ES6 Class 的主要概念,包括類別定義、建構子、方法定義、繼承,以及靜態方法,希望大家都能夠理解~!
參考資料:
文章同步於個人部落格:Viiisit!(歡迎參觀 ୧ʕ•̀ᴥ•́ʔ୨)