在当心翼翼维护项目代码的时候常常会看到这种代码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则是一种基本保障,确保检查无误才能运行。