TS 與 JS 誰好誰壞先不論,TS 新手如我很多事情也是在開發的時候慢慢了解的,這次想跟大家從 TS 與 JS 來談談編譯語言與直譯語言。
# TypeScript VS JavaScript
TypeScript(TS) 是微軟推出並且維護的一套基於 JavaScript(JS) 的程式語言,其特色在於實作型別、介面等。詳情可以看他們的官網。
在使用 TS 與 JS 有滿多不同的,但是其實他們最底層都還是執行 JS;換句話說,TS 如果真的要執行的話,要先轉換成 JS 然後才執行,這也就是為何 TS 與 JS 可以在同一個專案並存的原因,因為他們在骨子裡其實都是一樣的。
這個一樣的到底是怎麼回事?這個我們可以先看一下官網的教學
這邊可以發現教學說在執行 TS 檔案之前要先執行 TS 的編譯器
npx tsc
這個步驟有什麼用呢?這是因為一般常用的 JS 執行環境,也就是瀏覽器與 Node.js,其實無法辨別與執行 .ts
檔案,因為裡面有很多不是 JS 的語法,而 tsc
這個指令就是把這些 .ts
檔案編譯成 .js
檔,好讓 JS 的執行環境可以順利執行。
# 編譯與直譯
在初學 TS 的時候,我的 lead 說引入 TS 可以讓很多錯誤在編譯的時候就被找到,而不是在執行的時候才拋出錯誤。一開始聽到這段話我其實一知半解,因為 lead 在導入 TS 的時候已經把很多底層的指令都封裝打包好,讓大家在開發的時候只要依照以前下的指令即可,完全沒有自己有使用到 tsc
的感覺。直到我自己從頭開始建立 TS 專案,我才了解意思。
用以下的 code 來示範:
function arrayNumberMap(arr) {
return arr.map(Number);
}
function main() {
// some awsome code
if (someCondition) {
arrayNumberMap('123')
}
// some awsome code
}
對 JS 有基礎的人大概都會知道上面這段 code 有問題,當呼叫 arrayNumberMap
但是傳入一個 string,這會噴出錯誤:
Uncaught TypeError: arr.map is not a function
因為 string 並沒有這個 method,所以無法呼叫而出現錯誤。在 JS 這個錯誤要一直等到這段程式碼被執行才會噴出,也就是要呼叫到這個 function 並且傳入錯誤的參數,才會發現這個錯誤,所以如果沒有滿足條件而沒有呼叫到 function,有可能要等到上線時才發現這個錯誤。
但是類似的 code 在 TS 編譯的過程中可能就會被察覺。
function arrayNumberMap(arr: string[]): number[] {
return arr.map(Number);
}
function main(): void {
// some awsome code:
if (someCondition) {
arrayNumberMap('123')
}
// some awsome code
}
因為在 TS 中需要指定傳入參數的 type,所以類似的 code 在 TS 可以這樣改寫。而當我們使用 tsc
編譯的時候,TS 的編譯器會去偵測 code 然後發現有個地方使用 arrayNumberMap
的方法不正確而拋出錯誤,
Argument of type 'string' is not assignable to parameter of type 'string[]'.
這個時候整個程式碼其實尚未被執行,也就是說這個錯誤會在比較早的階段就被發現,不會到真正執行然後被觸發的時候才發現。
在這篇漫談會想要說這點,是因為前陣子看到的一個有趣討論進而去仔細看 TS 文件以及自己實驗才有更多理解。從動態語言與靜態?直譯與編譯?強型別與弱型別?與編譯語言 VS 直譯語言可以知道所謂編譯與直譯的差別,編譯是我們所寫的程式碼還需要先經過一層轉換,變成更底層的語言才可以執行,例如 C 語言;而直譯就是程式碼在執行時一邊編譯一邊執行,例如 python。編譯語言的型別錯誤會在編譯的時候就被發現,而直譯語言則是因為編譯與執行是連續的,所以要到執行的時候才會發現型別錯誤。
這樣來看 TS 與 JS 的話,JS 是直譯語言,在電腦上只要使用 Node.js 直接執行 .js
檔案就可以,不會要先編譯產生一個編譯好的檔案之後再執行編譯好的檔案;TS 則是要先經過 tsc
編譯,轉換成 .js
檔案之後才能被執行。所以 TS 在設計上會在編譯的時候就發現程式碼有地方發生型別錯誤,因此在轉換成 JS 時候就可以發現錯誤,不會等到轉換成 JS 並且執行的時候才發現。
關於作者
我是好人