flow學(xué)習(xí)筆記

簡介

JavaScript作為一種腳本語言是沒有參數(shù)類型這個(gè)概念的,所以在編寫代碼的時(shí)候可以給參數(shù)賦予任何類型的值。在寫JS的時(shí)候不用考慮參數(shù)類型、參數(shù)定義等等概念。當(dāng)項(xiàng)目逐漸變大,人員逐漸變動(dòng)的時(shí)候,沒有任何參數(shù)類型再加上代碼命名不規(guī)范,代碼將變得十分難以維護(hù)。面對一個(gè)參數(shù)變量不知道它是用來做什么的??赡軙?huì)有如下代碼:

main = () => {
   //fn1函數(shù)獲取了一個(gè)數(shù)據(jù)
   var object = fn1()
   //fn2根據(jù)獲數(shù)據(jù),產(chǎn)生一個(gè)結(jié)果
   var result = fn2(object)

   return result
}

Flow是個(gè)JavaScript的靜態(tài)類型檢查工具,所謂類型檢查,就是在編譯期盡早發(fā)現(xiàn)(由類型錯(cuò)誤引起的)bug,又不影響代碼運(yùn)行(不需要運(yùn)行時(shí)動(dòng)態(tài)檢查類型),使編寫 JavaScript 具有和編寫強(qiáng)類型語言相近的體驗(yàn)。

由于之前是寫Objective-C的,對于類型檢查還是比較能接受的。雖然在編寫代碼的時(shí)候會(huì)繁瑣一些,但是由于提前聲明了參數(shù)的類型,使用起來會(huì)更加的“放心”。


以下代碼實(shí)踐均在react native項(xiàng)目中實(shí)踐

安裝

npm install --save-dev flow-bin

創(chuàng)建配置文件。

touch .flowconfig

先不管空白的.flowconfig配置文件。在package.json文件里flow腳本。
your project/package.json

  "scripts": {
    "flow": "flow; test $? -eq 0 -o $? -eq 2",
  },

然后給需要flow檢查的文件里加上//@flow或者/*@flow*/。然后就可以檢查了。(也可以在命令中加上--all, 這樣就會(huì)檢查所有文件)。

在根目錄下運(yùn)行命令:

npm run flow

以上就配置好了flow

使用

Flow最重要的功能就是允許在參數(shù)前添加類型注釋,即規(guī)定該參數(shù)的數(shù)據(jù)類型。Flow內(nèi)置了很多的數(shù)據(jù)類型,有些是給原生類型用的,像 numberstringanymixed 比較寬松,沒有把值的類型限定死,而其他字面類型則描述某一種類型。

基本數(shù)據(jù)類型

Flow中常用的基本數(shù)據(jù)類型有number、stringboolean

注意,這里的類型都是小寫開頭的

他們的用法大致相同。都是在參數(shù)中聲明該參數(shù)的類型,下面是一個(gè)使用number的例子。

// js
plus = (x, y) => {
    return x + y;
} 

// @flow
plus = (x: number, y: number) : number => {
    return x + y;
}
plus(1, 2); // 正常返回3
plus('1', 2); // 報(bào)錯(cuò):Cannot call `plus` with `'1'` bound to `x` because string [1] is incompatible with number [2].

// 可以看到使用了Flow之后,當(dāng)傳入了不符合預(yù)先聲明的類型時(shí)Flow就會(huì)報(bào)錯(cuò),當(dāng)然這些錯(cuò)誤并不影響代碼的運(yùn)行。
// 不僅可以在定義函數(shù)的時(shí)候使用,而且可以在初始化變量的時(shí)候,就指定這個(gè)參數(shù)的類型,這和強(qiáng)類型語言的體驗(yàn)相似
let number1: number = 5;
let number2: number = '5'; // 報(bào)錯(cuò)

復(fù)合數(shù)據(jù)類型

Flow中也內(nèi)置了相關(guān)的復(fù)合數(shù)據(jù)類型,如Array、Object、Function

注意,這里的類型都是大寫開頭的

他們的使用方式和基礎(chǔ)數(shù)據(jù)類型差不多,不過Array在聲明的時(shí)候,不僅可以聲明這個(gè)參數(shù)是數(shù)組類型,還可以聲明這個(gè)數(shù)組里面的數(shù)據(jù)類型。

// @flow
let List1: Array<number> = [1];
let List2: Array<string> = ['21', '22'];
let List3: Array<boolean> = [false];

getFirst = (list: Array<number>) : number => {
    return list[0];
}

任何數(shù)據(jù)類型

當(dāng)不確定一個(gè)參數(shù)的類型時(shí),可以使用mixed來聲明該參數(shù),但是在使用的時(shí)候必須要判斷這個(gè)參數(shù)的類型,否則Flow會(huì)報(bào)錯(cuò)。

// @flow
plus = (y: mixed) : number => {
    if (typeof y === 'number') {
        return y;
    } else {
        return 1;
    }
}
// mixed是混合類型的意思 

如果不希望這個(gè)參數(shù)被Flow檢查,可以使用any即任意類型。如果頻繁使用any來聲明參數(shù)類型,那么Flow就沒有任何意義了,盡量還是避免使用any。

枚舉類型

Flow支持自定義的一些參數(shù)類型,不僅僅局限于它內(nèi)置的幾個(gè)??梢允褂肍low輕松的實(shí)現(xiàn)一個(gè)枚舉類型。

// @flow
type myType = 'A' | 'B' | 'C';
let testType: myType = 'A';
// 定一個(gè)枚舉,聲明的參數(shù)如果是該枚舉類型,那么它的值一定是在枚舉類型中。

可選的參數(shù)類型

當(dāng)一個(gè)參數(shù)不確定是什么類型的時(shí)候,上述的mixed可以實(shí)現(xiàn)但是并不常用,通常使用的是|來聲明多個(gè)參數(shù)類型,或者使用?來代替mixed

// @flow
plus = (y: ?number) : number => {
    if (typeof y === 'number') {
        return y;
    } else {
        return 1;
    }
}
// 這個(gè)?和mixed是一樣的,意思是這個(gè)參數(shù)可能是number類型,當(dāng)然也有可能是其他的類型。那么在使用的時(shí)候就需要對參數(shù)的類型判斷
// 如果參數(shù)的類型有兩個(gè),也就是說可能是number類型也可能是string類型,可以使用|來將所有的可能的參數(shù)類型列舉出來
plus = (y: number | string) : number => {
    if (typeof y === 'number') {
        return y;
    } else {
        return 1;
    }
}
// 和上述的一樣,使用之前都需要判斷參數(shù)的類型才能使用

關(guān)于?的使用

Flow中的?有兩種使用方法,一個(gè)是在參數(shù)前表明這個(gè)參數(shù)是可選的,另一個(gè)是在數(shù)據(jù)類型前表示可能是這個(gè)參數(shù)類型,也可能是其他的類型。

// @flow
let number2: ?number = 43; // 意思是這個(gè)參數(shù)有可能是number類型
let string2: ?string = '12'; 

plus = (x?: number, y: number) : number => {
    return x + y;
}
// 這里的?意思是這個(gè)x參數(shù)可能不存在

在React Native中使用

在React Native自定義組件的時(shí)候,F(xiàn)low可以用來聲明其需要的屬性,比如

// @flow
// 該組件的屬性
type Props = {
  text?: string,
  pointerEvents?: boolean,
  timeout?: number,
  onLoadingTimeout?: Function,
  offsetY?: number,
};  
// 組件
export default class Loading extends React.Component<Props> {
  static defaultProps = {
    pointerEvents: false,
    timeout: 0,
    offsetY: 0,
  };
}

在自定義組件中不僅可以定義從父組件傳遞的參數(shù),還可以定義默認(rèn)屬性。其他的用法和上述用法是相同的。

總結(jié)

Flow本質(zhì)上也只是個(gè)檢查工具,它并不會(huì)自動(dòng)修正代碼中的錯(cuò)誤,也不會(huì)強(qiáng)制說你沒按照它的警告消息修正,就不會(huì)讓你運(yùn)行程序。當(dāng)然,并沒有要求什么時(shí)候一定要用這類的工具,只是這種作法可以讓你的代碼更具強(qiáng)健性與提高閱讀性,也可以直接避去很多不必要的數(shù)據(jù)類型使用上的問題,這種開發(fā)方式目前在許多框架與函數(shù)庫項(xiàng)目,或是以JavaScript應(yīng)用為主的開發(fā)團(tuán)隊(duì)中都已經(jīng)都是必用工具,在React、Vue源碼中均在使用。

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容