---
# System prepended metadata

title: TypeScript Manual
tags: [教學]

---

# TypeScript Manual

## var / let / const
**var** 存在 **Hoisting**, **Scoping**, **Capturing** 等三大問題
**let** 則是為了解決 var 的問題而誕生，你可以把他理解為 C# 的 var
**const** 與 let 相似，差別在於 const 是不會變動的

## async / await
**Promise** 提供的語法糖，讓非同步函數的寫法向同步函數靠攏, 但不支援取消的功能

---
### 類似C#的region用法
```
// #region ABC
   ...
// #endregion
```
---
### 類似C#的summary用法
在多行註解 **/\* \*/** 的前半段, 多加一個星號
```
/**測試*/
function test():void { }
```

---

### namespace alias
C# 用 **using**, TypeScript 用 **import**
```
import GParticleSys = particle.GravityParticleSystem;
```

---

### 存取 namespace 內的自訂 class
class 前面加上 **export**
```
namespace ABC{
    export class XYZ{
        static do():void{}
    }
}
```
```
ABC.XYZ.do();
```

---

### 註冊鍵盤按下事件

```
init():void {
    document.addEventListener("keydown", this.onKeydown);
}

onKeydown(evt:KeyboardEvent):void {
    
    //判斷是否按下空白鍵, 2種不同的用法
    if(evt.key == " "){}
    if(evt.code == "Space"){}

    //這裡的 this 是 document
    //如果直接呼叫 this.OnExecute() 一定找不到, 要呼叫class實體才行
}

onExecute():void {}
```

為了避免混淆, 可以這樣寫, 但目標 function 必須是公開的
```
document.addEventListener("keydown", function(evt:KeyboardEvent){
    //這裡再去呼叫 class的實體.onExecute()
});
```
或者這樣寫, 就可以用 **this**
```
document.addEventListener("keydown", (evt:KeyboardEvent) => {
    this.onExecute();
});
```

### 多按鍵偵測
* 單純註冊 keydown 事件, 一次只會觸發一個按鍵事件, 無法同時處理多個按鍵, 解法如下
1. 需要註冊 **keydown** 和 **keyup** 事件來設定 flag
2. 註冊 **ENTER_FRAME** 事件 (作用和 unity MonoBehaviour 的 Update() 相同)
3. 在 **ENTER_FRAME** 觸發的 callback 裡面自行判斷
```
this.addEventListener(egret.Event.ENTER_FRAME, 自訂callback, this);
```

* [Key code 對應表](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values)
---

### js轉換ts

(判斷A) && (function A) => 判斷A為true時 執行A
(判斷B) || (function B) => 判斷B為false時 執行B

## js:
```
var MyClass = (function () {
    function MyClass() { }
    Object.defineProperty(MyClass.prototype, "View", {
        get: function () {
            return this.view;
        },
        set: function (value) {
            this.view = value;
        },
        enumerable: true,
        configurable: true
    });
    return MyClass;
})();
```

## ts:
```
class MyClass {
    private view;
    get View() { return this.view; }
    set View(value) { this.view = value }
}
```

## Array 操作
### Cannot read property 'push' of undefined
```
let myArray: number[]; // 沒有設定初始值
array.push(obj); // error occur: Cannot read property 'push' of undefined
```
:::danger
編譯後的 Javascript 為：
```
let myArray; <--- undefined
array.push(obj);
```
:::

```
let myArray: number[] = []; // 設定初始值
array.push(obj);
```

:::success
編譯後的 Javascript 為：
```
let myArray = []; <--- define as array
array.push(obj);
```
:::

---
## 如何避免VS自動產生 .js 和 .map 檔案
:::success
專案目錄新增 **tsconfig.json** 輸入以下內容
```
{
  "compilerOptions": {
    "outDir": "資料夾名稱"
  }
}
```
:::

---
### module 和 namespace 的差異
| | module | namespace |
|--|--| --|
| ts 1.5以前的名稱 | external module | internal module |
| 如何引用 | 需要先 import | 直接呼叫 |
| export差異 | 需要加上 export | export代表對外開放 |

---

### iframe雙向溝通
* parent to child
```typescript
target: HTMLIFrameElement;
...
target.contentWindow.postMessage("訊息", "*");
```
* child to parent
```typescript
window.parent.postMessage("訊息", "*")
```
* 事件接收
```typescript=
window.addEventListener("message", this.onEvent, false);
...
onEvent = (evt:MessageEvent) => {
    console.log(evt.data);
};
```

---

## 字串比較
:::success
使用 [localeCompare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare)
```typescript=
let a = "AAA";
let b = "aaa";

console.log(a.localCompare(b, "en", { sensitivity: "case" }));
```


| sensitivity 參數 | 基本字母 | 大小寫 | 輕重音 |
| -- | -- | -- | -- |
| base  | <font color="red">檢查</font> | 忽略 | 忽略 |
| accent | <font color="red">檢查</font> | 忽略 | <font color="red">檢查</font> |
| case | <font color="red">檢查</font> | <font color="red">檢查</font> | 忽略 |
| variant (預設值) | <font color="red">檢查</font> | <font color="red">檢查</font> | <font color="red">檢查</font> |

```typescript=
let a = "Antonio"
let b = "antónio"

console.log("base => " + a.localeCompare(b, "en", { sensitivity: 'base' }));
console.log("accent => " + a.localeCompare(b, "en", { sensitivity: 'accent' }));
console.log("case => " + a.localeCompare(b, "en", { sensitivity: 'case' }));
console.log("variant => " + a.localeCompare(b, "en", { sensitivity: 'variant' }));

/*輸出結果
base => 0
accent => -1
case => 1
variant => -1
*/
```

[參考文件](https://www.techonthenet.com/js/string_localecompare.php)
:::

---

## 學習資源
* [MagicLen的TypeScript學習之路](https://magiclen.org/tag/typescript-學習之路/)
* [Do's and Don'ts](https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html)

###### tags: `教學`