JavaScript 中的類別

JavaScript 中的類別

這篇文章解釋了 JavaScript 中的類別。

YouTube Video

JavaScript 中的類別

在 JavaScript 中,類別 包含了 物件導向程式設計 的概念,並作為物件的藍圖。使用類別可以簡潔地定義物件的 屬性方法,從而提高程式碼的重用性和組織性。類別語法在 JavaScript 的 ES6 中引入。

類別定義

類別透過 class 關鍵字定義,並通常由被稱為 構造函式(constructor) 的方法初始化。

 1class Person {
 2    // Constructor method (called when the class is instantiated)
 3    constructor(name, age) {
 4        this.name = name; // Property definition
 5        this.age = age;
 6    }
 7
 8    // Method definition
 9    greet() {
10        return `Hello, my name is ${this.name}`;
11    }
12}
13
14// Instantiation of the class
15const alice = new Person("Alice", 25);
16console.log(alice.greet()); // Hello, my name is Alice
  • 我們使用 class Person 定義一個 類別
  • constructor 是一個特殊的方法,在建立物件時會自動被呼叫。
  • 在類別內,this 關鍵字指向類別的實例(物件)。

類別屬性和方法

類別可以定義 屬性方法。屬性表示物件的特徵,方法則代表它的功能。

 1class Car {
 2    constructor(brand, model) {
 3        this.brand = brand;
 4        this.model = model;
 5    }
 6
 7    // Method definition
 8    drive() {
 9        console.log(`Driving a ${this.brand} ${this.model}`);
10    }
11}
12
13const car1 = new Car("Toyota", "Corolla");
14car1.drive(); // Driving a Toyota Corolla

在此範例中,宣告了一個 Car 類別,其中包含 brandmodel 屬性,並且有一個 drive 方法。

類別繼承

類別可以從其他類別 繼承。透過繼承,您可以基於現有的類別建立一個新類別,並為其增加額外的功能。

 1class Animal {
 2    constructor(name) {
 3        this.name = name;
 4    }
 5
 6    speak() {
 7        console.log(`${this.name} makes a noise`);
 8    }
 9}
10
11// Inherit from the Animal class
12class Dog extends Animal {
13    constructor(name, breed) {
14        super(name); // Call the constructor of the parent class (Animal)
15        this.breed = breed;
16    }
17
18    // Override the method
19    speak() {
20        console.log(`${this.name} barks`);
21    }
22}
23
24const dog = new Dog("Rex", "German Shepherd");
25dog.speak(); // Rex barks

在此範例中,Dog 類別繼承自 Animal 類別。

  • 使用 extends 關鍵字來繼承 Animal 類別。
  • Dog 類別的構造函式中,使用 super() 呼叫父類別的構造函式。這使您能繼承父類別的初始化過程。
  • 在繼承的類別中,您可以覆寫父類別的方法。在此範例中,顯示的是 "Rex barks" 而不是 "Rex makes a noise"。

靜態方法

當你在類內定義一個靜態方法時,該方法與類本身相關聯。靜態方法可以不用生成實例就能被調用。

1class MathUtils {
2    // Static method
3    static add(a, b) {
4        return a + b;
5    }
6}
7
8console.log(MathUtils.add(5, 10)); // 15

在這個例子中,MathUtils類定義了一個靜態方法add

  • static關鍵字用於定義靜態方法。
  • 靜態方法不屬於類的實例,可以直接從類本身調用。

取值方法與設值方法

通過在類中定義取值方法設值方法,可以封裝屬性的獲取與設置。

 1class Rectangle {
 2    constructor(width, height) {
 3        this.width = width;
 4        this.height = height;
 5    }
 6
 7    // Getter
 8    get area() {
 9        return this.width * this.height;
10    }
11
12    // Setter
13    set widthValue(newWidth) {
14        this.width = newWidth;
15    }
16}
17
18const rect = new Rectangle(10, 20);
19console.log(rect.area); // 200
20
21rect.widthValue = 15;
22console.log(rect.area); // 300

在此例中,Rectangle類定義了一個area取值方法和一個widthValue設值方法。

  • 取值方法 (get) 在獲取屬性值時被調用。
  • 設值方法 (set) 在設置屬性值時被調用。

類的語法糖

在JavaScript中,類的語法在內部是使用構造函數原型實現的。類的語法是對這些語法的一種語法糖,使它們更簡潔。

 1// Example without using class syntax
 2function Person(name, age) {
 3    this.name = name;
 4    this.age = age;
 5}
 6
 7Person.prototype.greet = function() {
 8    return `Hello, my name is ${this.name}`;
 9};
10
11const person = new Person("Alice", 25);
12console.log(person.greet()); // Hello, my name is Alice

在此例中,定義了一個Person構造函數,並使用原型定義了greet方法。

處理 this

類中的this關鍵字引用該類的實例。然而,在處理類方法中的this時,需注意其行為可能會根據作用域而有所不同。特別是在將方法用作回調函數時可能會出現問題。

 1class Counter {
 2    constructor() {
 3        this.count = 0;
 4    }
 5
 6    increment() {
 7        this.count++;
 8        console.log(this.count);
 9    }
10}
11
12const counter = new Counter();
13setTimeout(counter.increment, 1000); // NaN
14// NaN, since this.count is undefined, it becomes NaN after incrementing.

在這種情況下,當作為回調傳遞給setTimeout時,this的參考可能會改變。為避免此類問題,建議使用bind方法固定this,或使用箭頭函數。

 1class Counter {
 2    constructor() {
 3        this.count = 0;
 4    }
 5
 6    increment() {
 7        this.count++;
 8        console.log(this.count);
 9    }
10}
11
12const counter = new Counter();
13
14// When using bind
15setTimeout(counter.increment.bind(counter), 1000);
16
17// When using an arrow function
18setTimeout(() => counter.increment(), 2000);

總結

  • 用作創建對象的藍圖,定義屬性和方法。
  • 可以使用繼承擴展一個類,利用面向對象的概念。
  • 靜態方法屬於類本身,無需創建實例即可使用。
  • 可以使用取值方法設值方法封裝屬性。
  • JavaScript 的類別語法是語法糖,內部使用基於原型的繼承。

通過使用類別,您可以更自然地處理面向物件的編程,並提高代碼的可重用性和可維護性。

您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。

YouTube Video