js的由弱變強之路,Flow為js新增編譯過程
javascript是一門弱型別語言, 所謂弱型別, 就是一個變數既可以被賦值 字串
, 數字
, 又可以被賦值 陣列
, 物件
, 弱型別的好處很多, 但也有缺點, 比如:
- 跳過了編譯過程, 導致程式碼中的錯誤只能在執行時才能顯現出來
- 由於變數的型別靈活多變, 導致程式碼可讀性降低, 不容易排錯
- 由於變數形式靈活多變, 導致IDE的智慧提示不夠準確
Facebook的Flow

- 官網地址: ofollow,noindex">https://flow.org/

- github開源地址: https://github.com/facebook/flow
Facebook開發了一個名為 Flow
的框架, 為javascript添加了編譯的過程, 可以讓我們用類似java的 強型別風格
, 編寫js語言, 使用方法非常簡單, 以下是flow的一些使用例項
初始化一個npm專案
// 新建一個資料夾 mkdir learn-flow // 進入資料夾 cd learn-flow // 初始化專案 npm init -y
安裝flow
npm install flow-bin
在 package.json
中新增啟動指令碼
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "flow": "flow" },

建立flow配置檔案 .flowconfig
npm run flow init

使用方法
原js程式碼:
var userName = "zhaoolee"; var userAge = 22;
非破壞式的寫法(通過註釋)
- 在專案
learn-flow
中新建一個user.js
檔案
//@flow var userName /*: string*/ = "zhaoolee"; var userAge /*: number*/ = 18;
注意點: 需要在檔案首部新增 //@flow標記
, 否則無法進行型別檢測
進行型別檢測
npm run flow

如果宣告與賦值的型別不匹配,則會產生報錯資訊

flow中支援檢測的型別有哪些呢?
number: 數字, NaN, Infinity, 寫法如下
//@flow var num1 /*: number*/ = 100; var num2 /*: number*/ = NaN; var num3 /*: number*/ = Infinity;
string: 字串, ,寫法如下
//@flow var name /*: string*/ = "zhaoolee";
null: 就是 null
, ,寫法如下
//@flow var likePython /*: null*/ = null;
boolean: 就是布林型別, 寫法如下
// @flow var likePython /*: boolean*/ = true;
void: 在flow中, undefined屬於void, 寫法如下
//@flow var isUndefined /*: void*/ = undefined;
any: 表面可以使用任何型別, 這個相當於js原生的型別(動態),寫法如下
//@flow var nameOrAge /*: any*/ = "zhaoolee"; nameOrAge = 123;
Array: 陣列型別, 定義時,需要指定陣列內元素的型別, 寫法如下
//@flow var names /*: Array<string>*/ = ["zhaoolee", "Alan", "Amy", "Alice"]; var ages /*: Array<number>*/ = [18, 22, 16, 21]; var nameOrAge /*: Array<any>*/ = ["zhaoolee", 22, "Amy", 21];
Object: 物件型別, 寫法如下
- 對object的每個屬性進行檢查
//@flow var dog = { name: "wang", age: 14, } function sayNameAndAge(animal /*:{name: string, age: number}*/ ) { console.log("name==>", animal.name, " | ", "age==>", animal.age); } sayNameAndAge(dog);
Function: 函式型別, 寫法如下

//@flow function cal(num1 /*: number*/ , signs /*: string*/ , num2 /*: number*/ ) /*: number*/ { var result /*: number*/ = 0; switch (signs) { case "+": result = num1 + num2; break; case "-": result = num1 - num2; break; case "*": result = num1 * num2; break; case "/": result = num1 / num2; break; } return result; } var num1 /*: number*/ = 100; var num2 /*: number*/ = 50; console.log(num1 + "與" + num2 + "之和為:", cal(num1, "+", num2)); console.log(num1 + "與" + num2 + "差值為:", cal(num1, "-", num2)); console.log(num1 + "與" + num2 + "乘積為:", cal(num1, "*", num2)); console.log(num1 + "與" + num2 + "相除為:", cal(num1, "/", num2));
Maybe: null和void型別的組合, 寫法如下:

//@flow function add(num1 /*: number*/ , num2 /*: ?number*/ ) /*: number*/ { var num1 = num1 | 0; var num2 = num2 | 0; return num1 + num2; } console.log(add(1));
或操作: 型別1 | 型別2, 寫法如下
- 如果需要某變數只能接受
string
和number型別
, 就需要用到或操作
, 寫法如下
//@flow var nameOrAge /*: string|number*/ = "zhaoolee"; nameOrAge = 12;
小結:
- 對於弱型別(動態型別)的語言, 好處很多,博主也非常喜歡弱型別,在《黑客與畫家》中有一段很有意思的話, 充分說明了動態語言的優勢

- 事實上, 在商業化的工程中, 類似java這種強型別(靜態型別)的語言, 編寫的專案,更容易做大
- 我周圍的人都喜歡python, 但也經常聽到吐槽: python太靈活了, 即使某個判斷分支有錯誤, 只要執行不到這一步, 就不會報錯, 這樣就讓工程的維護和排錯變得麻煩, 所以說Flow這種為動態語言新增編譯過程的工具, 還是蠻有用的, 所以, 不如花20分鐘學習一下Flow