--- 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 ###### 文章若有任何錯誤,還請不吝給予留言指正,謝謝大家!
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up