靜態型別在 JavaScript 中是一種負擔嗎?

Jothy發表於2018-11-26

靜態型別在 JavaScript 中是一種負擔嗎?

原文作者:UC 國際研發 Randy


寫在最前:歡迎你來到“UC國際技術”公眾號,我們將為大家提供與客戶端、服務端、演算法、測試、資料、前端等相關的高質量技術文章,不限於原創與翻譯。

最近我在公司的專案中遇到很多由於型別不匹配所導致的不可預估的問題。比如說,我們的程式產生了一個純數字的 unique id, 存到資料庫中被識別為 number 型別,但是客戶端需要的是字串,導致一條資料在沒有辦法在客戶端正常顯示。

我年輕的時候曾經是一位動態型別的忠實擁躉,因為動態型別方便、自由。假設在我需要編寫一段為我服務的小程式時,如果 runtime 強制需要我去做一些向上向下轉型的工作,恐怕我會崩潰。

但是,在享受自由的同時,我們卻很容易寫出這樣的程式:

靜態型別在 JavaScript 中是一種負擔嗎?

靜態型別在 JavaScript 中是一種負擔嗎?

這是一個用於生成簽名字串的函式,從邏輯上看,這段程式碼沒有問題。但是,當另一個對這個函式內部實現不瞭解的開發人員使用它時,會返回意想不到的結果:

靜態型別在 JavaScript 中是一種負擔嗎?

使用者希望把 timestamp 用作 salt,但是 signStr 並不是意料中的由 timestamp 和 appId 拼接而成的 signString, 而是 appIdtimestamp 相加的運算結果。而這種錯誤是在編譯時無法感知的。

然而,如果我們用靜態型別的 TypeScript 做同樣的事情:

靜態型別在 JavaScript 中是一種負擔嗎?

在編譯時,就會丟擲型別錯誤的提示,這時就會知道,你的 salt 應該用一個 toString() 來轉換成字串。



靜態型別在 JavaScript 中是一種負擔嗎?型別檢查是一種負擔嗎?

我認為不是。起碼在構建大規模的應用程式時,靜態型別會幫助你避免大多數的執行時錯誤。

而 code base 並不是衡量應用程式規模的唯一指標。只要符合以下某種情況,就認為這個程式是大規模的:

  1. code base 很大

  2. 超過 2 人維護的程式

  3. 被多人依賴的模組

在以上這些情況下,型別宣告變得尤為重要。你可能認為你能記住變數是什麼型別,但在程式的世界裡生存的不僅僅是字面量。

在團隊共同維護程式碼的時候,如果沒有型別宣告,你絕對有可能傳入一個非預期的引數。所以,型別宣告是開發者與開發者之間的傳達資訊的過程——我要的是什麼型別,你就只能給我什麼型別。

型別宣告也是開發者給編輯器傳達資訊的手段。只有顯示的型別宣告,編輯器和 IDE 才能判斷函式中的形參應該有怎樣的行為,才能給開發者正確的程式碼提示,才能安全地為你進行 Refact.

靜態型別在 JavaScript 中是一種負擔嗎?



靜態型別在 JavaScript 中是一種負擔嗎?靜態型別的 JavaScript

JavaScript 雖然是一門物件導向的語言,但相對於 C++, Java 這類語言來說,它的抽象能力很弱。在構建大規模的 JavaScript 應用程式時,我常常懷念寫 Java (Android) 時可以寫 interface, 可以寫 abstract. 在編寫 JavaScript 程式中,很難舒服地運用一些設計模式。

We designed TypeScript to meet the needs of the JavaScript programming teams that build and maintain large JavaScript programs.
——

TypeScript Language Specification

TypeScript 引入了 Interface, Enum, Generic, abstract class 等等,這些表達能力正是在構建大規模 JavaScript 程式時所缺失的。不是說沒有 TypeScript, ECMAScript 就不能實現這些,而是 TypeScript 在程式碼層面賦予了這些約定。

比如,用 TypeScript 實現 Singleton:

靜態型別在 JavaScript 中是一種負擔嗎?

理論上,被編譯出來的 ECMAScript 程式碼照樣可以順利地 new Person(), 但 TypeScript 會在編譯時提醒你,這個類不應該被例項化。

我不打算在本文對 TypeScript 作出詳細的指南,我只希望大家可以認識到,嚴謹的型別檢查和麵向物件表達能力對程式碼的健壯性和可維護性有很大的正面作用。ECMAScript 是一門自由靈活的語言,但絕不代表我們就應該為這種靈活承擔過高的出錯概率。況且,TypeScript 在嚴格型別檢查的同時,又保留了 ECMAScript 的自由性(你甚至可以用 any 型別來規避型別檢查)。

我永遠認為使用沒有型別驗證的 JavaScript 會讓我快樂,無論她有多大的坑。我仍然可以用她愉快地寫指令碼搶這個搶那個,用她來寫各種各樣的 bot,無須考慮型別轉換。但當我用她來寫一些不是為了讓我快樂的程式的時候,我希望她在執行時不要跑偏,還希望她長得像真正的 OOP 。

靜態型別的 JavaScript 就像開始做手機後的羅永浩,你能看出他們的妥協,他們本不是這樣。但他們是真正要上場合了,才不得不這樣,即使他們根本不是你喜歡的樣子。


好文推薦:

2019年前端面試都聊啥?一起來看看



“UC國際技術”致力於與你共享高質量的技術文章

歡迎關注我們的公眾號、將文章分享給你的好友

靜態型別在 JavaScript 中是一種負擔嗎?



相關文章