看一段常见代码:
function foo(x) { return x + 10 }
foo('Hello!') function main(params){ var object = fn1(params) var result = fn2(object) return result
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
例2很明显,这个过程非常的‘黑’,如果你想知道object包含什么数据的话,可以:
-
打印一下 console.log(object)
-
查看fn1的注释,并且保佑它的注释是正确,全面的
-
或结合1,2,然后仔细查看fn1的源码,希望它不是很复杂
被上述步骤折磨完之后,终于能真正的写点代码了,但是依旧得非常小心,因为这里还有另一个函数:fn2
在修改代码的时候,得保证result这个结果没有被影响,那么如何保证呢?
很简单,重复上面的步骤,搞清楚result包含的数据,在测试的时候确保其数据跟原先的相同。
…
动态类型一时爽,代码重构火葬场
知乎传送门:为什么说“动态类型一时爽,代码重构火葬场”
是时候彻底优化这个烦人的问题了
引入类型系统
其实问题的根源就是因为javascript太灵活了,在代码运行期间几乎可以做任何的修改,
没有东西可以在代码层面保证 某个变量,某个函数 跟预期的一致。
所以要加入类型系统来确保代码的可靠性,在后期维护的时候同样能够传达出有效的信息
Flow & TypeScript
Flow是个JavaScript的静态类型检查工具,由Facebook出品的开源码项目,问世只有两三年,是个相当年轻的项目。简单来说,它是对比TypeScript语言的解决方式。
会有这类解决方案,起因是JavaScript是一种弱(动态)数据类型的语言,弱(动态)数据类型代表在代码中,变量或常量会自动依照赋值变更数据类型,而且类型种类也很少,这是直译式脚本语言的常见特性,但有可能是优点也是很大的缺点。优点是容易学习与使用,缺点是像开发者经常会因为赋值或传值的类型错误,造成不如预期的结果。有些时候在使用框架或函数库时,如果没有仔细看文件,亦或是文件写得不清不楚,也容易造成误用的情况。
这个缺点在应用规模化时,会显得更加严重。我们在团队开发协同时,一般都是通过统一的代码规范,来降低这个问题的发生,但JS语言本身
无法有效阻止这些问题。TypeScript这样的强(静态)类型的JavaScript超集语言就开始流行,用严格的角度,以JavaScript语言为基底,来重新打造另一套具有强(静态)类型特性的语言,就如同Java或C#这些语言一样,这也是为什么TypeScript称自己是企业级的开发JavaScript解决方案。
TypeScript存在的问题
TypeScript自然有它的市场,但它有一些明显的问题:
-
首先是JavaScript开发者需要再进一步学习,内容不少
-
有一定陡峭的学习曲线
-
已经在使用的应用代码,需要整个改用TypeScript代码语法,才能发挥完整的功用。这对很多已经有内部代码库的大型应用开发团队而言,将会是个重大的决定,因为如果不往全面重构的路走,将无法发挥强(静态)类型语言的最大效用eg:angular2
*所以许多现行的开源码函数库或框架,并不会直接使用TypeScript作为代码的语言,另一方面因为TypeScript并非是普及到一定程度的语言。
当然TypeScript也是个活跃的开源码项目,发展到现在也有一段时间,它的背后有微软公司的支持,全新打造过的Angular2框架中(由Google主导),也采用了TypeScript作为基础的开发语言*。
Flow你的新选择
现在,Flow提供了另一个新的选项,它是一种强(静态)类型的辅助检查工具
。Flow的功能是让现有的JavaScript语法可以事先作类型的声明(定义),在开发过程中进行自动检查
,当然在最后编译时,一样可以用babel工具来移除这些标记。
相较于TypeScript是另外重新制定一套语言,最后再经过编译为JavaScript代码来运行。Flow走的则是非强制与非侵入性的路线。
Flow的优点
-
轻
且易学易用
它的学习曲线没有TypeScript来得高,虽然内容也很多,但半天学个大概,就可以渐进式地开始使用
-
Flow从头到尾只是个
检查工具
不是新的程序语言或超集语言,所以它可以与各种现有的JavaScript代码兼容,如果你哪天不想用了,就去除掉标记就是回到原来的代码,没什么负担
so
选择flow.js工具而不选择TypeScript强类型语言的原因显而易见?
flow.js对工程的侵入性很小,无需大量的额外工作就能使用起来
从一个小例子演示
这种类型不符的情况在代码中非常容易发生,例如上面的例1:
function foo(x) { return x + 10 }
foo('Hello!')
x这个传参,我们在函数声明时希望它是个数字类型,但最后使用调用函数时则用了字符串类型。最后的结果会是什么吗? “Hello!10”,这是因为加号(+)在JavaScript语言中,除了作为数字的加运算外,也可以当作字符串的连接运算。想当然这并不是我们想要的结果。
聪明如你应该会想要用类型来当传参的识别名,容易一眼看出传参要的是什么类型,像下面这样:
function foo(number) { return number + 10 }
-
如果在复合类型的情况,例如这个传参的类型可以是数字类型也可以是布尔类型,你又要如何写得清楚?
-
如果是个复杂的对象类型时,结构又该如何先确定好?
-
另外还有函数的返回类型又该如何来写?
利用Flow类型的定义方式,来解决这个小案例的问题,可以改写为像下面的代码:
function foo(x: number): number { return x + 10 }
foo('hi')
当使用非数字类型的值作为传入值时,就会出现由Flow工具发出的警告消息,像下面这样:
[flow] Cannot call foo
with 'hi'
bound to x
because string 1 is incompatible with number 2. (a.getting-start.js:6:5)
如果是要允许多种类型也是很容易可以加标记的,假使这个函数可以使用布尔与数字类型,但返回可以是数字或字符串,就像下面这样修改过:
function foo(x: number | boolean): number | string { if (typeof x === 'number') { return x + 10 } return 'x is boolean' }
foo(1)
foo(true)
foo(null)
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
在多人协同开发某个有规模的JavaScript应用时,这种类型的输出输入问题就会很常遇见。如果利用Flow工具的检查,可以避免掉许多不必要的类型问题。
真实案例
可能你会认为Flow工具只能运用在小型代码中,其实不然,Vue源码中大量使用flowjs中类型检测:
Flow使用
1. flow init
2. // @flow 或 /* @flow */
3. IDE插件 或 flow check
在Visual Studio Code中因为它内建TypeScript与JavaScript的检查功能,如果要使用Flow工具来作类型检查,需要在用户设置中,加上下面这行设置值以免冲突:
“javascript.validate.enable”: false
4 . babel插件在编译时就会一并转换Flow标记
{
"plugins": [ "transform-flow-strip-types" ] }
Flow支持的数据类型
Flow支持原始数据类型,如下面的列表:
-
boolean
-
number
-
string
-
null
-
void
类型别名&常见语法
export type Test = {
titleOne?: string,
titleTwo: ?string
} var a: Test = {titleOne:"3",titleTwo:4} var b:string = "" export type NavigationGestureDirection = 'horizontal' | 'vertical';
type T = Array<string> var x: T = []
x["Hi"] = 2 type TT = Array<Test> var xx:TT = []
xx = [{titleOne: '1',
titleTwo: false}]
type MyObject = {
foo: number,
bar: boolean,
baz: string,
};
let val:MyObject = {foo:2,bar:false,baz:'444'}; var val1: MyObject = {foo:2,bar:false,baz:null}; var val2: MyObject = {foo:2,bar:false}; function method(val: MyObject):MyObject { return {foo:2,bar:false,baz:'2'}} class Foo { constructor(val: MyObject) { } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
React中的应用
如果你在React class里面使用了React.PropTypes规范,你可以对JSX上的attributes做静态类型检查:
var Hello = React.createClass ({
propTypes: {
name: React.PropTypes.string.isRequired
} ... });
//<Hello/> //Flow就会发现 缺少属性的错误
//<Hello name={42}/>//属性类型的错误
import * as React from 'react'; type Props = {
foo: number,
bar?: string,
}; function MyComponent(props: Props) {
props.doesNotExist; // Error! You did not define a `doesNotExist` prop. return <div>{props.bar}</div>;
}
<MyComponent foo={42} />
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
更多关于支持React的细节 请移步 https://flow.org/en/docs/react/components/
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务