# **TypeScript 針對 iOS 不支持 JIT 的優化策略總結**
由于 iOS 的 **JavaScriptCore (JSC)** 引擎 **禁用 JIT(Just-In-Time 編譯)**,JavaScript 在 iOS 上的執行性能較差,尤其是涉及動態代碼時。 ?
**TypeScript(TS)** 通過 **靜態類型檢查** 和 **編譯時優化**,可以顯著減少動態行為,提升 iOS 上的運行效率。 ?
以下是 **推薦寫法 vs 避免寫法** 的對比分析,以及各自的 **性能影響** 和 **優化原理**。
---
## **1. 靜態屬性訪問 vs 動態屬性訪問**
### ? **推薦寫法:靜態屬性訪問**
```typescript
interface User {
? ? name: string;
}
const user: User = { name: "Alice" };
console.log(user.name); // 靜態訪問
```
**好處**:
- **引擎優化友好**:iOS 的 JavaScriptCore(JSC)引擎可以 **提前計算屬性偏移**,直接訪問內存位置,減少哈希查找開銷。
- **AOT 友好**:靜態結構更容易被 **提前編譯(AOT)** 優化,減少解釋執行時的性能損耗。
### ? **避免寫法:動態鍵訪問**
```typescript
const user: Record<string, string> = { name: "Alice" };
const key = "name";
console.log(user[key]); // 動態訪問
```
**問題**:
- **哈希查找開銷**:引擎無法預知 `key` 的值,必須進行 **運行時哈希計算**,性能較差。
- **無法內聯優化**:動態訪問阻止 JSC 進行 **內聯緩存(Inline Caching)**,導致每次訪問都要重新查找。
---
## **2. 使用 `Map` 代替 `Object` 存儲動態鍵**
### ? **推薦寫法:`Map` 結構**
```typescript
const map = new Map<string, number>();
map.set("score", 100);
console.log(map.get("score")); // 比 `obj[key]` 更快
```
**好處**:
- **優化哈希表**:`Map` 專為動態鍵設計,查找速度比 `Object` 更快(尤其在頻繁增刪鍵時)。
- **內存更緊湊**:`Map` 存儲方式比 `Object` 更高效,減少內存碎片。
### ? **避免寫法:`Object` 動態鍵**
```typescript
const scores: Record<string, number> = {};
scores["math"] = 90;
console.log(scores["math"]); // 動態鍵性能較差
```
**問題**:
- **隱藏類(Hidden Class)變更**:動態增刪屬性會導致引擎重建隱藏類,增加開銷。
- **哈希沖突風險**:`Object` 的哈希表實現不如 `Map` 高效,可能影響性能。
---
## **3. 避免 `any`,使用顯式類型**
### ? **推薦寫法:顯式類型**
```typescript
function add(a: number, b: number): number {
? ? return a + b; // 引擎可推斷類型,優化計算
}
```
**好處**:
- **減少類型檢查**:引擎無需在運行時動態推斷類型,直接使用 **固定類型優化**。
- **更快的函數調用**:參數類型明確,iOS JSC 可生成更高效的調用路徑。
### ? **避免寫法:隱式 `any`**
```typescript
function add(a, b) { // 編譯后變成 `function add(a: any, b: any)`
? ? return a + b; // 運行時需檢查類型
}
```
**問題**:
- **額外類型檢查**:引擎必須在運行時檢查 `a` 和 `b` 的類型,降低執行速度。
- **無法內聯優化**:動態類型阻止 JSC 進行 **函數內聯(Inlining)** 優化。
---
## **4. 使用 `const` 和 `readonly` 固定引用**
### ? **推薦寫法:不可變引用**
```typescript
const arr: readonly number[] = [1, 2, 3]; // 不可變數組
console.log(arr[0]); // 引擎可優化訪問
```
**好處**:
- **內存優化**:引擎知道數組不會被修改,可以 **預分配內存** 或 **靜態優化訪問**。
- **減少隱藏類變更**:避免動態修改導致引擎重建內部結構。
### ? **避免寫法:動態修改**
```typescript
const arr = [1, 2, 3]; // 可變數組
arr.push(4); // 修改數組結構
```
**問題**:
- **隱藏類重建**:每次修改數組/對象結構,引擎可能 **重新計算內存布局**,降低性能。
- **解釋執行更慢**:動態修改的代碼在 iOS 上解釋執行時更慢。
---
## **5. 減少運行時類型檢查**
### ? **推薦寫法:編譯時類型約束**
```typescript
function parse(input: string) { // 編譯時確保類型正確
? ? return input.trim();
}
```
**好處**:
- **無運行時開銷**:引擎直接處理 `string` 類型,無需額外檢查。
### ? **避免寫法:運行時類型檢查**
```typescript
function parse(input: unknown) {
? ? if (typeof input === "string") return input.trim(); // 運行時檢查
}
```
**問題**:
- **額外分支判斷**:`typeof` 檢查增加 CPU 開銷,影響性能。
- **阻止優化**:動態類型檢查讓引擎難以優化代碼路徑。
---
## **6. 啟用 TS 嚴格模式**
### ? **推薦寫法:`strict: true`**
```json
// tsconfig.json
{
? ? "compilerOptions": {
? ? ? ? "strict": true,
? ? ? ? "noImplicitAny": true
? ? }
}
```
**好處**:
- **強制顯式類型**,避免意外動態行為。
- **更早發現潛在性能問題**,如隱式 `any` 或未定義類型。
### ? **避免寫法:寬松模式**
```json
{
? ? "compilerOptions": {
? ? ? ? "strict": false // 允許隱式 any
? ? }
}
```
**問題**:
- **隱藏性能問題**:代碼可能包含大量動態類型,降低 iOS 運行效率。
---
## **7. 使用 WebAssembly(WASM)優化計算密集型任務**
### ? **推薦寫法:WASM + TS 類型安全**
```typescript
import wasmModule from "./compute.wasm";
const result = wasmModule.exports.heavyCalculation();
```
**好處**:
- **繞過 JS 引擎限制**:WASM 是 AOT 編譯的,不依賴 JIT,在 iOS 上性能穩定。
- **適用于游戲/加密/圖像處理** 等計算密集型場景。
### ? **避免寫法:純 JS 計算**
```typescript
function heavyCalculation() {
? ? // 純 JS 計算,iOS 上可能很慢
? ? let sum = 0;
? ? for (let i = 0; i < 1e6; i++) sum += i;
? ? return sum;
}
```
**問題**:
- **解釋執行慢**:iOS 無 JIT,循環和計算性能較差。
---
## **總結:TS 在 iOS 上的優化核心思路**
| **優化方向** ? ? ? ? ?| **推薦寫法** | **避免寫法** | **iOS 性能影響** |
|----------------------|------------|------------|----------------|
| **屬性訪問** ? ? ? ? ?| `obj.prop` | `obj[key]` | ? 快 2-5x |
| **數據結構** ? ? ? ? ?| `Map` ? ? ?| `Object` ? | ? 快 1.5-3x |
| **類型定義** ? ? ? ? ?| 顯式類型 ? | `any` ? ? ?| ? 快 2x |
| **不可變性** ? ? ? ? ?| `readonly` | 動態修改 ? | ? 快 1.5x |
| **類型檢查** ? ? ? ? ?| 編譯時檢查 | `typeof` ? | ? 快 2x |
| **計算密集型任務** ? ?| WASM ? ? ? | 純 JS ? ? ?| ? 快 10-100x |
### **關鍵結論**
1. **靜態 > 動態**:盡量讓代碼結構在編譯時確定,減少運行時決策。
2. **AOT 優化友好**:iOS 無 JIT,靜態代碼更容易被 AOT 或解釋器優化。
3. **WASM 突破瓶頸**:對計算密集型任務,用 WASM 替代 JS。
通過以上優化,即使 iOS 不支持 JIT,也能讓 TypeScript 代碼運行得更快! 🚀