# Typescript 特色 * JavaScript 的一種超集 * 強型別 * 支援可選的靜態類型 * 支援介面(Interface) * 支援泛型(Generics) * 支援枚舉(Enum) * 使用自動垃圾回收(Garbage Collection)來管理記憶體 --- # 基本語法 ## Variable & Constant (變數和常數) * **名稱字元** 1. 字母:A-Z,a-z 2. 數字:0-9 (不能以數字開頭) 3. 底線:_ * **命名規則** **1. Camel Case (駝峰式命名)** > userName > fileName **2. Snake Case (Snake Case 命名法)** > user_name > file_name **3. Pascal Case (帕斯卡式命名)** > UserName > FileName ![1](https://hackmd.io/_uploads/ry_8OJsva.png) * 變數可以加型別也可以不加型別 * 常數不可以賦值後另外再改變 ![image](https://hackmd.io/_uploads/HJwgvkiPT.png) --- ## Variable (變數類型) ![2](https://hackmd.io/_uploads/HJFKnJiPp.png) * number: 數字,包括整數和浮點數。 * string: 字符串。 * boolean: 布林值,只能是 true 或 false。 * null: 表示缺少值或空值。 * undefined: 表示未初始化的值。 * any: 表示一個變數可以是任何類型。 * Union Types: 聯合類型,允許一個變數具有多種可能的類型。 * Template Strings: ${}模板字符串: 允許在字符串中插入變數或表達式 ![image](https://hackmd.io/_uploads/H1D2a1sPa.png) --- ## Operator (運算子) **1. 算術運算子:** * +:加法 * -:減法 * *:乘法 * /:除法 * %:取餘 **2. 關係運算子:** * ==:等於 * ===:嚴格等於(型別也會判斷) * !=:不等於 * !==:嚴格不等於(型別也會判斷) * \>:大於 * <:小於 * \>=:大於等於 * <=:小於等於 **3. 邏輯運算子:** * &&:邏輯與(AND) * ||:邏輯或(OR) * !:邏輯非(NOT) **4. 位元運算子:** * &:位元與 * |:位元或 * ^:位元異或 * ~:位元非 * <<:左位移 * \>>:右位移 **5. 賦值運算子:** * =:賦值 * +=、-=、*=、/=、%=:複合賦值 **6. 三元運算子:** * condition ? expr1 : expr2: 如果 condition 為真,返回 expr1,否則返回 expr2 --- ## Enum (枚舉) ![3](https://hackmd.io/_uploads/S1UYxxsw6.png) * enum: 為一組相關的常數提供了一個有意義的名稱,使程式更具可讀性。 * 默認從0開始也可以自己賦值 * type: 用於定義新的類型,能夠為現有的類型創建一個別名。 ![image](https://hackmd.io/_uploads/B1KW-loPa.png) --- ## Array(陣列) ![9](https://hackmd.io/_uploads/SyIC5TCPp.png) * let numbers: number[] : 定義一個包含數字的陣列 * let numbers: Array<int> : 使用 Array<T> 語法 * numbers.**push**(x) : 將一個或多個元素添加到陣列的末尾。 * numbers.**pop**() : 刪除陣列的最後一個元素。 * numbers.**shift**() : 刪除陣列的第一個元素。 * numbers.**unshift** (x) : 將一個或多個元素添加到陣列的開頭。 * numbers.**slice**(x, y) : 返回陣列[x, y-1] * numbers.**splice**(x, y) : 從索引 x 開始刪除 y 個元素。 * numbers.**reverse**() : 反轉陣列的順序。 * numbers.**sort**() : 對陣列的元素進行排序。 * numbers.**indexOf**(x) : 返回指定元素x的索引,如果找不到則返回 -1。 * arr1.**concat**(arr2) : 連接兩個或多個陣列,返回一個新陣列。 --- ## Generics (泛型) 1. **代碼重用和靈活性**:允許編寫能夠適用於多種類型的代碼,而不必針對每種類型編寫重複的邏輯。這使得代碼更具重用性和靈活性。 2. **類型安全**:提供了一種在編譯時檢查類型的機制,避免了在運行時由於類型錯誤導致的問題。這有助於提高代碼的可靠性和維護性。 3. **抽象數據結構和算法**:可以創建抽象的數據結構和算法,而不必關心實際的數據類型。 4. **與現有庫和框架的兼容性**:可以更容易地與現有的庫和框架進行集成,以處理各種類型的數據。 5. **更清晰的API設計**:可以用於設計更清晰和通用的 API,使得 API 更易於理解和使用。 ![15](https://hackmd.io/_uploads/HyhRwlkdp.png) --- ## For Loop Iteration (迴圈迭代) ![4](https://hackmd.io/_uploads/Hyqs9eoDp.png) * for...in: 用於迭代對象的index * for...of: 用於迭代對象的值 * forEach: 對每個元素都應用指定的回調函數。這個回調函數接收三個參數,分別是: 1. 元素的值(value): 陣列中當前遍歷的元素的值。 2. 元素的索引(index): 陣列中當前遍歷的元素的索引。 3. 原始陣列(array): 正在遍歷的陣列本身。 --- ## Function (函式) ![5](https://hackmd.io/_uploads/r16hf-oDT.png) **1. 函數宣告(Function Declaration):** * **特點**:提供一個具名函數,可以在任何地方使用。 * **適用情境**: 通常在整個scope中都需要使用函數時使用。 **2. 函數表達式(Function Expression):** * **特點**:使用變數賦值給一個函數,函數可以匿名也可以命名。 * **適用情境**: 如果函數僅在特定的區塊或運算中使用,可以使用函數表達式。 **3. 箭頭函數(Arrow Function):** * **特點**:簡潔的函數表達式,它使用 => 語法。 * **適用情境**: 當函數只有一行時,且不需要使用 this。 **4. 選擇性參數(Optional Parameters):** * **特點**:使用 ? 來表示,允許在函數調用時不提供該參數,這樣該參數將被視為undefined。 * **適用情境**: 當某個參數可能存在但不一定需要被提供時使用。 **5. 默認參數(Default Parameters):** * **特點**:直接在函數聲明中給定初始值,當該參數在函數調用時未提供值時,將使用默認值。 * **適用情境**: 當某個參數通常有一個常見的默認值時使用。 **6. 剩餘參數(Rest Parameters):** * **特點**: 可以處理不定數量的附加參數,將它們收集到一個陣列中。 * **適用情境**: 當函數需要接受可變數量的參數時使用。 --- ## Callback function (回調函式) * **非同步操作**: 用於處理非同步操作,例如檔案讀取、網路請求、計時器等。 當非同步操作完成時,回調函數被呼叫以處理結果。 * **事件處理**: 在事件驅動的程式設計中,回呼函數通常用於處理特定的事件,例如按鈕點擊、滑鼠移動等。 當事件發生時,相關的回調函數被呼叫。 * **靈活性**: 透過回呼函數,可以將某些特定的行為(程式碼邏輯)傳遞給函數,使得函數能夠在不同的上下文中執行不同的操作。 * **參數傳遞**: 回呼函數通常接受一定數量的參數,這些參數包含在呼叫回呼函數的上下文中,以便在回呼函數內部使用。 * **錯誤處理**: 回呼函數也可以用來處理錯誤,例如在非同步操作中,當出現錯誤時,可以呼叫特定的錯誤處理回呼函數。 ![10](https://hackmd.io/_uploads/Hy4cMR0Pp.png) --- ## Asynchronous function (非同步函式) * **非同步** : 同步的程式語言遇到非同步的事件時,會將非同步的事件移動到程式碼的最後方,等到所有的原始碼運行完以後才會執行非同步的事件。 * **Promise** : 是用來優化非同步的語法結構, * **Async、Await** : 可以基於 Promise 讓非同步的語法的結構類似於 “同步語言”,更易讀且好管理。 ### Promise * **什麼是 Promise?** **Promise** 是 JavaScript 或 TypeScript 中用於處理異步操作的一個對象。它代表了一個可能在未來完成或失敗的操作,並提供一個統一的、可預測的方式來處理這些操作的結果。 **Promise** 本身是一個**建構函式**,函式也是屬於物件的一種,因此可以附加其它屬性方法在上 ![image](https://hackmd.io/_uploads/BkDh1hRwp.png) * Promise 建構函式建立同時,必須傳入一個函式作為參數(executor function),此函式的參數包含 **resolve**, **reject**,這兩個方法分別代表成功與失敗的回傳結果,特別注意這兩個僅能回傳其中之一,回傳後表示此 Promise 事件結束。 * **Promise 的狀態:** **Pending** (進行中):Promise 的初始狀態,表示操作尚未完成。 **Fulfilled** (成功):表示操作成功完成,並返回一個resolve結果。 **Rejected** (失敗):表示操作未成功完成,並返回一個rejected錯誤。 ![7](https://hackmd.io/_uploads/H1uASfjv6.png) * **Resolve & Reject** 這兩個函數是由 Promise 的執行體(executor)中提供的回調函數所接收的,它們用於將 Promise 從未定(pending)的狀態轉換為已解決(fulfilled)或已拒絕(rejected)的狀態。 * **.then() & .catch()** .then() 方法用於處理 Promise 成功的情況。它接受一個或兩個回調函數作為參數 .catch() 方法用於處理 Promise 失敗的情況。它接受一個回調函數作為參數,這個回調函數處理 reject 函數中傳遞的錯誤。 ### Async/Await * **什麼是 Async/Await?** **async/await** 是 JavaScript 中處理異步操作的一種語法,它使得異步程式碼的撰寫和理解更加簡單。它建立在 Promise 的基礎上,提供了一種更同步風格的編碼方式。 * **簡化異步程式碼**: **async/await** 語法簡化了異步程式碼,使其看起來更像同步程式碼,提高了可讀性。 * **同步風格的錯誤處理**: 使用 **try/catch** 塊可以方便地捕獲異步操作中的錯誤,提供更優雅的錯誤處理機制。 ![8](https://hackmd.io/_uploads/B1jtX6CwT.png) * **async function** : 可以用來定義一個非同步函式,讓這個函式本體是屬於非同步,但其內部以“同步的方式運行非同步”程式碼。 * **await** : await 是屬於一元運算子,它會直接回傳後方表達式的值;但如果是 Promise 時則會暫停非同步函式的運行(中止 Promise 的運行),直到非同步進入 resolve 或 reject,當接收完回傳值後繼續非同步函式的運行。 * 參考資訊 : [JavaScript Promise 全介紹](https://www.casper.tw/development/2020/02/16/all-new-promise/) [Async function / Await 深度介紹](https://www.casper.tw/development/2020/10/16/async-await/) --- ## export & import (導出和導入) * 在TypeScript中,使用**export**和**import**語句來定義模塊(Module),這使得代碼可以分割成多個文件,提高代碼的可維護性和可讀性。 * **export** : 用於將變量、函數、類或模塊進行導出,使其可以在其他文件中使用。 1. **named export(命名導出)**:導出前必須給予特定名稱,而導入時也必須使用相同的名稱。另外,**一個檔案中可以有多個** named export。 2. **default export(預設導出)**:**一個檔案僅能有唯一的** default export,而此類型不需要給予名稱。 * **import** : 用於導入模塊中的變量、函數、類等。 * **default** 關鍵字通常用於模組系統(Module System)。模組是一種組織和封裝 TypeScript 程式碼的方式,使其可以被其他程式碼引入和重複使用。 * 想**重新命名**導入(導出)的變數、函數、或類,可以使用 as 關鍵字指定一個新的名稱。 ![16](https://hackmd.io/_uploads/BJB2OJlup.png) --- # OOP (物件導向) * **Class、Object、Method、Property**: * **Class (類別)**: 一種抽象的數據類型,描述了物件的屬性和行為。 * **Object (物件)**: 類別的實例,具有屬性和方法。。 * **Method (方法)**: 與類別或對象相關聯的函數。 * **Property (屬性)**: 與類別或對象相關聯的變數。 1. **Encapsulation (封裝)**: * 將數據和相關的操作(方法)封裝在一個單位(類別)中的概念。 * 類別通常提供 **公開(public)、私有(private)和受保護(protected)** 等不同層次的訪問權限。 2. **Inheritance (繼承)**: * 一種類別之間的關係,允許一個類別(子類別)繼承另一個類別(父類別)的屬性和方法。 * 有助於重用代碼並建立層次結構,子類別可以擁有父類別的特性並添加自己的功能。 3. **Polymorphism (多型)** : 表示同一類型的物件可以在不同的情況下表現出不同的行為。多型主要有以下三種形式: 1. **Parametric Polymorphism (參數多型)** : 一種泛型(Generic)的形式,可以使函數或類別在操作不同型別的數據時保持彈性。 2. **Subtype Polymorphism (子類型多型)** : 繼承和介面實現的一種形式,允許父類型的變數引用子類型的實例,並以多態的方式呼叫方法。 3. **Operator Overloading Polymorphism (運算子多型)** : 一種使運算子具有不同行為的能力,取決於操作的物件類型。 ## Constructor & Static (建構式和靜態) * **Constructor (構造函數)**: 一個特殊的方法,在創建類別的實例時被調用。它通常用來初始化類別的成員屬性,以及執行一些額外的初始設定。 * **Access Modifiers (存取修飾符)**: TypeScript 提供了三種存取修飾符,分別是 public、private 和 protected,用來控制成員的可訪問性。 * **Member Properties (成員屬性)** : 定義在類別中的變數,用來描述物件的狀態。它們通常在類別的構造函數中進行初始化,並且可以在整個類別中被訪問。 * **Member Methods (成員方法)**: 定義在類別中的函數,用來定義類別的行為。它們可以訪問類別的成員屬性,並執行一些操作。 * **Static Properties (靜態屬性)** : 屬於類別本身而不是類別的實例。這些屬性在整個類別的生命週期中只存在一份,並且可以直接透過類別名稱訪問,而不需要實例化類別。 * **Static Members (靜態成員)**: 屬於類別本身而不是實例,可以通過類別名直接訪問。使用 static 關鍵字聲明靜態成員。 ![11](https://hackmd.io/_uploads/rkB6dCRwa.png) --- ## Destructor(解構式) * TypeScript(以及JavaScript)中,並沒有像某些其他語言(例如C++)中的 "Destructor" 概念。在JavaScript和TypeScript中,內存管理由垃圾回收器(Garbage Collector)負責,開發者不需要手動釋放內存或定義類似於 "Destructor" 的方法。 * **垃圾回收器** : 負責追蹤不再使用的對象並釋放相應的內存。在JavaScript和TypeScript中,物件不再被引用時,它將被標記為"可回收",並在垃圾回收器執行時進行釋放。 * 在類別中,如果有一些資源需要手動釋放(例如關閉連接、清理計時器等),開發者通常會提供一個 destroy 或 dispose 方法 --- ## Inheritance (繼承) * **Inheritance (繼承)** : 允許一個類別(子類別)使用另一個類別(父類別)的屬性和方法。子類別可以繼承父類別的特性,同時還可以擴展或修改這些特性。 * **extends** : 用於建立類別之間的繼承關係。當一個類別(子類別)需要使用另一個類別(父類別)的屬性和方法時,可以使用 extends 來建立繼承。 * **super** : 用於呼叫父類別(或父類別的原型)的屬性和方法。它通常用於子類別的構造函數中,以調用父類別的構造函數。 ![12](https://hackmd.io/_uploads/HJdnw11_a.png) --- ## Abstract & Interface (抽象和介面) ### Abstract VS Interface * **Abstract Class (抽象類別)** : 1. 可以包含實際的實作程式碼,可以有實例屬性和實例方法。 2. 透過 **abstract** 關鍵字定義,可以包含抽象方法(方法沒有實際實現,必須在衍生類別中實現)。 3. 一個類別只能繼承自**一個**抽象類別。 * **Interface (介面)** : 1. 不能包含實際的實作程式碼,只能包含屬性和方法的定義。 2. 透過 **interface** 關鍵字定義。 3. 一個類別可以實作**多個**介面。 * **Extends** 1. 類別繼承 2. 介面繼承 ### Abstract * **Abstract Class (抽象類別)**: 1. **抽象類別不能被實例化**: 抽象類別主要用於被繼承,不能直接創建實例 2. **抽象類別可以包含實現的方法**: 除了抽象成員外,抽象類別可以包含實現的方法。 * **Abstract Members (抽象成員)**: 1. **抽象成員必須在派生類別中實現**: 派生類別(子類別)必須提供抽象類別中聲明的抽象成員的實現。 2. **抽象成員不能包含實現**: 抽象成員只能在抽象類別中聲明,而不能包含實際的實現。 3. **派生類別必須實現所有抽象成員**: 如果派生類別沒有實現抽象類別中聲明的所有抽象成員,則該派生類別本身也必須標記為抽象。 ![13](https://hackmd.io/_uploads/r1tIwyJu6.png) ### Interface * **implements** : 用於類別實現(implement)一個或多個介面。該類別將提供介面中定義的所有成員,包括屬性和方法。 1. **實現單個介面**:使用 implements 來表示一個類別實現一個介面。 2. **實現多個介面**:一個類別可以同時實現多個介面,使用逗號分隔介面名稱。 3. **類別繼承和介面實現的同時存在**:一個類別可以同時繼承另一個類別並實現一個或多個介面。先繼承再實現,使用 extends 和 implements。 ![14](https://hackmd.io/_uploads/By95Gxk_6.png) # Design Pattern (設計模式) 1. 建立型模式 2. 結構型模式 3. 行為型模式 4. 併發型模式 ## Singleton Pattern (單例模式) * **Singleton Pattern (單例模式)**: 一種創建型設計模式,確保某個類別只有一個實例,並提供一個全局訪問點。在需要共享資源、限制特定類型的實例數量或確保唯一性的情況下非常有用。 1. **私有構造函數**: 通過將構造函數標記為私有,防止直接通過 new 關鍵字創建實例。 2. **私有靜態實例**: 使用一個私有靜態成員(instance)來保存實例,並確保只有一個實例。 3. **靜態方法 getInstance**: 這個方法負責創建實例,如果還沒有創建過的話。在這個方法中,首先檢查 instance 是否存在,如果不存在則創建一個新的實例。 4. **使用時的唯一性**: 通過 getInstance 方法獲取實例,確保每次獲取的都是同一個實例。 ![17](https://hackmd.io/_uploads/rJE3iygu6.png) --- ## ...To Do