September 26, 2023

Viiisit [JavaScript] - ES6 Class 語法糖!

#javascript#class

在上篇因為 JavaScript 沒有原生的 Class,所以他的繼承方式是以 prototype (原型),在 ES6 中引入了 Class(類別)語法,他是一種語法糖,提供了更容易使用的方式來建立和管理物件以及實現物件導向程式(OOP)的概念。這種語法糖使得在 JavaScript 中建立和使用類型更加直觀和類似傳統的類型語言(如 Java 或 C++ )。

ES5 類似 Class 概念

在 ES5 中,雖然沒有像 ES6 中的 Class 語法那樣的類別概念,但我們可以使用 Constructor function(建構式函式)和 Prototype(原型)來實現類似的物件和繼承模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

我們將上方例子轉換為 ES6 的 Class 語法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 之間的差異:


ES6 的 Class - 繼承概念

我們已經看到如何使用 ES6 的 Class 語法來定義和創建一個簡單的 Food 類別,
以及如何建立食物的實例。
接著,我們將繼續探討 ES6 中的類別繼承概念:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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 關鍵字調用父類別的建構子。

最後,我們建立一個 cake 實例,並使用 describeenjoy 方法來展示繼承和子類別獨有的功能。


ES6 的 Class - 靜態方法

我們已經探討了如何使用 ES6 的 Class 語法來定義類別,以及如何使用繼承來建立類別之間的層次結構。
現在,我想介紹 ES6 中的類別靜態方法的概念。

靜態方法是與類別本身相關聯的方法,而不是與類別的實例相關聯,他用於執行與整個類別相關的操作。
如果希望做到某個專屬於這個原型的方法,在 ES6 中,你可以使用 static 關鍵字來定義靜態方法。

繼續銜接上面的 Food 來說明類別靜態方法的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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() 靜態方法來判斷這些食物是否健康。


Brief Summary

ES6 中的 Class 語法為 JavaScript 引入更接近傳統物件導向程式設計的方式,使得在 JavaScript 中建立和管理物件更加直觀且容易。今天分享 ES6 Class 的主要概念,包括類別定義、建構子、方法定義、繼承,以及靜態方法,希望大家都能夠理解~!


References:
ES6 中的 class 是什麼?
MDN - Classes
JavaScript | ES6 中最容易誤會的語法糖 Class - 基本用法