在當心翼翼維護項目代碼的時候常常會看到這種代碼javascript
function main(){ //fn1函數獲取了一個數據 var object = fn1() //fn2根據獲數據,產生一個結果 var result = fn2(object) return result }
很明顯,這個過程很是的‘黑’,若是你想知道object包含什麼數據的話,能夠html
打印一下 console.log(object)前端
查看fn1的註釋,而且保佑它的註釋是正確,全面的java
或結合1,2,而後仔細查看fn1的源碼,但願它不是很複雜node
被上述步驟折磨完以後,終於能真正的寫點代碼了,可是依舊得很是當心,由於這裏還有另外一個函數:fn2。webpack
在修改代碼的時候,得保證result這個結果沒有被影響,那麼如何保證呢?git
很簡單,重複上面的步驟,搞清楚result包含的數據,在測試的時候確保其數據跟原先的相同。github
…web
是時候完全優化這個煩人的問題了。npm
其實問題的根源就是由於javascript太靈活了,在代碼運行期間幾乎能夠作任何的修改,
沒有東西能夠在代碼運行前就保證 某個變量,某個函數 跟預期的一致。
因此要加入類型系統來確保代碼的可靠性,在後期維護的時候一樣可以傳達出有效的信息。
facebook出品的flow.js 作的就是這種事情。
git 倉庫:https://github.com/facebook/flow
flow 官方文檔:https://flowtype.org/docs/qui...
方便體驗,這裏有一個搭好的case集合
git clone git@github.com:JavascriptTips/flow-examples.git
flow.js 中定義了的5種最簡單的類型,(warning:都是小寫),其中void對應js中的undefined
boolean
number
string
null
void
要想加入到javascript中,只須要在關鍵的地方聲明想要的類型。其它時間咱們的代碼仍是熟悉的javascript,代碼以下(flow-examples工程中也有對應js文件):
//flow-examples/src/primitives.js //在文件的頭部加入,用註釋加入 `@flow` 聲明,這樣flow.js纔會檢查這個文件。 //@flow //在聲明變量時,在變量名加入 `:[Type]` 來代表變量的類型,其它類型同理。 //這個語法很是像flash的ActionScript,咦?好像暴露了什麼。 var num:number = 1; var str:string = 'a'; //固然,也能夠不加類型,這樣就跟原來的js同樣了。 var variable = 'zz';
主要有:
Object
Array
函數
自定義Class
這幾個類型比較複雜,並且能夠相互嵌套。在flow.js中這幾種類型有很是多的檢查語法,在這裏簡單的展現幾項,具體見代碼代碼和官方文檔。
//flow-examples/src/object.js //@flow //Object大寫的O var o:Object = { hello:'h' }; //聲明瞭Object的key var o2:{key:string} = { key:'z233' };
//flow-examples/src/array.js //@flow //基於基本相似的數組,數組內都是相同類型 var numberArr:number[] = [12,3,4,5,2]; //另外一個寫法 var numberAr2r:Array<number> = [12,3,2,3]; var stringArr:string[] = ['12','a','cc']; var booleanArr:boolean[] = [true,true,false]; var nullArr:null[] = [null,null,null]; var voidArr:void[] = [ , , undefined,void(0)]; //數組內包含各個不一樣的類型數據 //第4個原素沒有聲明,則能夠是任意類型 var arr:[number,string,boolean] = [1,'a',true,function(){},];
函數比較特殊,由於函數的核心在於參數和返回值,函數做文類型自己並無做用。
//flow-examples/src/function.js //@flow /** * 聲明帶類型的函數 * 這裏是聲明一個函數fn,規定了本身須要的參數類型和返回值類型。 */ function fn(arg:number,arg2:string):Object{ return { arg, arg2 } } //同理,ES2015箭頭函數的寫法 var fn2 = (arg:number,arg2:string):Object => { return { arg, arg2 } } /** * 這裏是聲明變量fn2,規定了它所需的函數的特徵: * 參數: (arg:string,arg2:number) * 返回值:Object */ var fn3:(arg:string,arg2:number)=>Object = function(){ return {} } /** * 對比下面這種寫法, * 二者的聲明的地方不同,形成的意義也不一樣。 */ var fn4 = function(arg:string,arg2:Object):number{ return 1; }
聲明一個自定義類,而後用法如同基本類型
//flow-examples/src/class.js //@flow class MyClass{ name:string; constructor(n){ this.name = n; } } var myClass : MyClass = new MyClass('abc');
能夠看到加入flow.js語法後,正常的js引擎確定是不能跑的。
這時就要藉助萬能的babel編譯這些js。
1.若是是正經的帶webpack + babel 的前端項目,能夠無縫集成,加入babel插件便可:
babel-plugin-transform-flow-strip-types
2.若是隻是跑一下測試這些js,能夠直接在flow-examples工程中,以下:
npm run fnode src/object.js
其它跑起來的方法,能夠在官方文檔查看
這裏只是介紹了flow.js一部分的特性,在引入flow.js以後,js只須要很小的改動就能獲得加強,在關鍵的地方確保邏輯的準確性。
更進一步,再結合js的函數式編程特性,以類型和函數驅動開發,感受很cool.
這裏2個小問題,
爲何是flow.js 而不是其它編譯到js的強類型語言,如TypeScript ?
答:我很是喜歡js的靈活性,它爲編程帶來極大便捷。並且flow.js對工程的侵入性很小,無需大量的額外工做就能使用起來。
爲何不增強註釋,完善註釋,而是再加入一個工具?答:由於寫註釋很煩,而且有無註釋不會影響代碼執行。flow.js則是一種基本保障,確保檢查無誤才能運行。