Flow 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 作了静态类型检查,因此了解 Flow 有助于咱们阅读源码。html
JavaScript 是动态类型语言,它的灵活性有目共睹,可是过于灵活的反作用是很容易就写出很是隐蔽的隐患代码,在编译期甚至看上去都不会报错,但在运行阶段就可能出现各类奇怪的 bug。vue
类型检查是当前动态类型语言的发展趋势,所谓类型检查,就是在编译期尽早发现(由类型错误引发的)bug,又不影响代码运行(不须要运行时动态检查类型),使编写 JavaScript 具备和编写 Java 等强类型语言相近的体验。node
项目越复杂就越须要经过工具的手段来保证项目的维护性和加强代码的可读性。 Vue.js 在作 2.0 重构的时候,在 ES2015 的基础上,除了 ESLint 保证代码风格以外,也引入了 Flow 作静态类型检查。之因此选择 Flow,主要是由于 Babel 和 ESLint 都有对应的 Flow 插件以支持语法,能够彻底沿用现有的构建配置,很是小成本的改动就能够拥有静态类型检查的能力。git
一般类型检查分红 2 种方式:github
类型推断:经过变量的使用上下文来推断出变量类型,而后根据这些推断来检查类型。api
类型注释:事先注释好咱们期待的类型,Flow 会基于这些注释来判断。数组
它不须要任何代码修改便可进行类型检查,最小化开发者的工做量。它不会强制你改变开发习惯,由于它会自动推断出变量的类型。这就是所谓的类型推断,Flow 最重要的特性之一。数据结构
经过一个简单例子说明一下:函数
/*@flow*/`` function split(str) { return str.split(' ') } split(11)
Flow 检查上述代码后会报错,由于函数 split
期待的参数是字符串,而咱们输入了数字。工具
如上所述,类型推断是 Flow 最有用的特性之一,不须要编写类型注释就能获取有用的反馈。但在某些特定的场景下,添加类型注释能够提供更好更明确的检查依据。
考虑以下代码:
/*@flow*/ function add(x, y){ return x + y } add('Hello', 11)
Flow 检查上述代码时检查不出任何错误,由于从语法层面考虑, +
既能够用在字符串上,也能够用在数字上,咱们并无明确指出 add()
的参数必须为数字。
在这种状况下,咱们能够借助类型注释来指明指望的类型。类型注释是以冒号 :
开头,能够在函数参数,返回值,变量声明中使用。
若是咱们在上段代码中添加类型注释,就会变成以下:
/*@flow*/ function add(x: number, y: number): number { return x + y } add('Hello', 11)
如今 Flow 就能检查出错误,由于函数参数的期待类型为数字,而咱们提供了字符串。
上面的例子是针对函数的类型注释。接下来咱们来看看 Flow 能支持的一些常见的类型注释。
/*@flow*/ var arr: Array<number> = [1, 2, 3] arr.push('Hello')
数组类型注释的格式是 Array<T>
,T
表示数组中每项的数据类型。在上述代码中,arr 是每项均为数字的数组。若是咱们给这个数组添加了一个字符串,Flow 能检查出错误。
/*@flow*/ class Bar { x: string; // x 是字符串 y: string | number; // y 能够是字符串或者数字 z: boolean; constructor(x: string, y: string | number) { this.x = x this.y = y this.z = false } } var bar: Bar = new Bar('hello', 4) var obj: { a: string, b: number, c: Array<string>, d: Bar } = { a: 'hello', b: 11, c: ['hello', 'world'], d: new Bar('hello', 3) }
类的类型注释格式如上,能够对类自身的属性作类型检查,也能够对构造函数的参数作类型检查。这里须要注意的是,属性 y
的类型中间用 |
作间隔,表示 y
的类型便可以是字符串也能够是数字。
对象的注释类型相似于类,须要指定对象属性的类型。
若想任意类型 T
能够为 null
或者 undefined
,只需相似以下写成 ?T
的格式便可。
/*@flow*/ var foo: ?string = null
此时,foo
能够为字符串,也能够为 null
。
目前咱们只列举了 Flow 的一些常见的类型注释。若是想了解全部类型注释,请移步 Flow 的官方文档。
有时候咱们想引用第三方库,或者自定义一些类型,但 Flow 并不认识,所以检查的时候会报错。为了解决这类问题,Flow 提出了一个 libdef
的概念,能够用来识别这些第三方库或者是自定义类型,而 Vue.js 也利用了这一特性。
在 Vue.js 的主目录下有 .flowconfig
文件, 它是 Flow 的配置文件,感兴趣的同窗能够看官方文档。这其中的 [libs]
部分用来描述包含指定库定义的目录,默认是名为 flow-typed
的目录。
这里 [libs]
配置的是 flow
,表示指定的库定义都在 flow
文件夹内。咱们打开这个目录,会发现文件以下:
flow ├── compiler.js # 编译相关 ├── component.js # 组件数据结构 ├── global-api.js # Global API 结构 ├── modules.js # 第三方库定义 ├── options.js # 选项相关 ├── ssr.js # 服务端渲染相关 ├── vnode.js # 虚拟 node 相关
能够看到,Vue.js 有不少自定义类型的定义,在阅读源码的时候,若是遇到某个类型并想了解它完整的数据结构的时候,能够回来翻阅这些数据结构的定义。
经过对 Flow 的认识,有助于咱们阅读 Vue 的源码,而且这种静态类型检查的方式很是有利于大型项目源码的开发和维护。相似 Flow 的工具还有如 TypeScript,感兴趣的同窗也能够自行去了解一下。