---
# System prepended metadata

title: 跑完 JS30 就接著認識 TypeScript 入門｜Day10：認識類別 Class
tags: [跑完 JS30 就接著認識 TypeScript 入門]

---

---
GA: G-7BSJTG7RYN
---

我們都知道 `Class` 是 JavaScript 的語法糖，先來複習一下 MDN 對 [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 的說明：
> Classes are a template for creating objects.
> 類別是一個可以 **創建物件** 的模板

而經由類別創建的物件，有個特定的名稱叫做實體（`Instance`）。

事實上，概念和前一篇 `Interface` 有個相似之處－兩者都可以進行**抽象化**的行為。

若忘記**抽象化**是什麼，可以再複習一次 [型別化名](https://hackmd.io/@elzuoc/rkcMxJJx3#%E5%9E%8B%E5%88%A5%E5%8C%96%E5%90%8D-Type-Alias) 篇章針對抽象化的說明與範例。

> `抽象化`：將具體的細節隱藏起來，只提供一個接口或功能給使用者。

來看個簡單的範例：
```typescript=
class Rectangle {
  width: number;
  height: number;
}
```

是不是覺得很眼熟？
沒錯，這個用法與 [`Interface`](https://hackmd.io/@elzuoc/ryw1Am_xn) 極為相似，**不過**使用方式、目的，都與 `Interface` 大相逕庭。

宣告完 `interface` 後，我們可以直接拿來進行註記，就像 `型別化名` 一樣。

而 `class` 的作用則完全不同，目的是為了 **創建物件（= 實體 Instance）**，而創建的方式必須透過 `new` 這個關鍵字，才能夠創建：
```typescript=
const square = new Rectangle();
```

這時，我們才能取用這個物件中的屬性：
```typescript=
square.width = 100;
square.height = 100;
```

而我們也可以在一開始宣告 `class` 時，就初始化屬性值（`value`）。
> **請注意！！**
> 若直接拿這段程式碼到 TypeScript 的 [Playground](https://www.typescriptlang.org/play) 玩，會顯示錯誤，這不是語法錯誤，這與 `tsconfig` 的設定有關。

```typescript=
class Rectangle {
  width: 100;
  height: 100;
}
```

這時，我們取用物件屬性時，就可以直接取得初始化的值：

```typescript=
const square = new Rectangle();
console.log(square.width, square.height); // 100, 100
```
--
#### --strictPropertyInitialization
```typescript=
class Rectangle {
  width: number;
  height: number;
}
```
我們剛剛提到這段語法會顯示 `未初始化屬性值` 的錯誤，主要原因是 `tsconfig` 有個屬性 [`strictPropertyInitialization`](https://www.typescriptlang.org/tsconfig#strictPropertyInitialization) 預設值是 `true`。

表示在類別中初始化屬性值，必須透過 `constructor` ，我們稱之為 **建構子** 或 **建構式** 或 **建構函式**。

> `constructor`：專屬於類別中，用於建立物件（= **實體 Instance**）的**特殊**子程式。

既然稱為建構**函式**，那麼寫法就與 `function` 有點類似：
```typescript=
class Rectangle {
    width: number;
    height: number;
    
    // 建構式
    constructor() {
        this.width = 100;
        this.height = 100;
    }
}
```
`constructor` 的特殊性，就是會在使用 `new` 創建物件的同時，就自動執行 `constructor` 中的程式。

> **小知識：`this` 究竟指向誰？**
> 要談論 `this` 需要不少時間，不在本篇重點。
> 簡單來說，若在該作用域中不存在對應的屬性，`this` 就會往上一層找，直到找到所需的屬性。

再來多看一個應用 - `readonly`，它可使屬性值變成 **唯讀**，不可被修改。

```typescript=
class Rectangle {
    readonly width: number = 100;
    
    // 建構式
    constructor() {
        this.width = 50; // OK
    }

    changeVal(){
        this.width = 80; // ERROR
    }
}

const square = new Rectangle();
square.width = 40; // ERROR
```
當我們使用 `readonly` 初始化 `width` 值為 `100`，只有在 `contrustor` 中可以被修改成 `50`。

若在其他 **自訂函式**中 或 **創建物件（= 實體 Instance）** 後，要修改其值，則會顯示錯誤：
> Error: Cannot assign to 'width' because it is a read-only property.

最後，針對 `Instance` ，簡單再說明一次：
> An `instance` is an `object` created from a `class`. 
> `實體`：專指一個由 `類別` 創建而來的 `物件`。

多了一個新名詞，但可以在溝通上加強雙方共識，區分彼此是在說一般的物件，還是在討論類別創建而來的物件，也能夠在通靈的時候排除許多因素，讓分析更聚焦。


--
### 類別必學的四大性質
1. 抽象（Abstraction）
2. 封裝（Encapsulation）
3. 繼承（Inheritance）
4. 多型（Polymorphism）

抽象（化）的概念在本篇開頭已經提過，就不再贅述。

接下來的篇章會從 **封裝** 開始談，不過由於抽象化是一種行為，我們還是會持續看見它的蹤影。

---
### Reference
- [TypeScript Official Site - Interfaces](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces)
- [Classes (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
- [DEFINITION instance](https://www.techtarget.com/whatis/definition/instance)
---

> 系列：[`跑完 JS30 就接著認識 TypeScript 入門`](https://hackmd.io/@elzuoc?tags=%5B%22%E8%B7%91%E5%AE%8C+JS30+%E5%B0%B1%E6%8E%A5%E8%91%97%E8%AA%8D%E8%AD%98+TypeScript+%E5%85%A5%E9%96%80%22%5D)
> 上一篇：[Day09：認識介面 Interface](https://hackmd.io/@elzuoc/ryw1Am_xn)
> 下一篇：[Day11：認識類別 Class - 封裝 Encapsulation](https://hackmd.io/@elzuoc/HkVDUvFgh)

###### tags: [`跑完 JS30 就接著認識 TypeScript 入門`](https://hackmd.io/@elzuoc?tags=%5B%22%E8%B7%91%E5%AE%8C+JS30+%E5%B0%B1%E6%8E%A5%E8%91%97%E8%AA%8D%E8%AD%98+TypeScript+%E5%85%A5%E9%96%80%22%5D)

###### Created on ∥ March 23, 2023
###### 文章若有任何錯誤，還請不吝給予留言指正，謝謝大家！