Try   HackMD

我們都知道 Class 是 JavaScript 的語法糖,先來複習一下 MDN 對 Class 的說明:

Classes are a template for creating objects.
類別是一個可以 創建物件 的模板

而經由類別創建的物件,有個特定的名稱叫做實體(Instance)。

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

若忘記抽象化是什麼,可以再複習一次 型別化名 篇章針對抽象化的說明與範例。

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

來看個簡單的範例:

class Rectangle { width: number; height: number; }

是不是覺得很眼熟?
沒錯,這個用法與 Interface 極為相似,不過使用方式、目的,都與 Interface 大相逕庭。

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

class 的作用則完全不同,目的是為了 創建物件(= 實體 Instance),而創建的方式必須透過 new 這個關鍵字,才能夠創建:

const square = new Rectangle();

這時,我們才能取用這個物件中的屬性:

square.width = 100; square.height = 100;

而我們也可以在一開始宣告 class 時,就初始化屬性值(value)。

請注意!!
若直接拿這段程式碼到 TypeScript 的 Playground 玩,會顯示錯誤,這不是語法錯誤,這與 tsconfig 的設定有關。

class Rectangle { width: 100; height: 100; }

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

const square = new Rectangle(); console.log(square.width, square.height); // 100, 100

strictPropertyInitialization

class Rectangle { width: number; height: number; }

我們剛剛提到這段語法會顯示 未初始化屬性值 的錯誤,主要原因是 tsconfig 有個屬性 strictPropertyInitialization 預設值是 true

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

constructor:專屬於類別中,用於建立物件(= 實體 Instance)的特殊子程式。

既然稱為建構函式,那麼寫法就與 function 有點類似:

class Rectangle { width: number; height: number; // 建構式 constructor() { this.width = 100; this.height = 100; } }

constructor 的特殊性,就是會在使用 new 創建物件的同時,就自動執行 constructor 中的程式。

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

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

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


系列:跑完 JS30 就接著認識 TypeScript 入門
上一篇:Day09:認識介面 Interface
下一篇:Day11:認識類別 Class - 封裝 Encapsulation

tags: 跑完 JS30 就接著認識 TypeScript 入門
Created on ∥ March 23, 2023
文章若有任何錯誤,還請不吝給予留言指正,謝謝大家!