一、js
是一种弱类型、动态类型检查的语言。
-
弱类型:在定义变量时,可以为变量定义复制任何数据,变量的数据类型不是固定死的,这样的类型叫做弱类型。
var a = 10; a = "abc"; a = []; a = function() {};
-
强类型:在声明变量时,一旦给变量赋值,那么变量的数据类型就已经确定,之后如果要给该变量赋值其他类型的数据,需要进行强制数据类型转换。
int a = 6; a = "10";
-
动态类型与静态类型的核心区别
动态类型的类型检查是是在代码运行的时候进行的,静态类型的类型检查则是在编译时进行。 运行时类型检查--->`js`: 动态类型,类型检查的操作是在运行时进行的; 代码中的错误,只能在代码运行的时候被发现。影响代码效率和稳定性。
-
静态类型的优势
(1)提早发现代码中的bug;
function greet(obj){ obj.sayHello(); //报错没有该方法 } var o = { name: "张学友" } greet(o);
(2)提高代码的可读性
// 如果能指定a和b的类型 // 指定为数字,这个函数的功能就非常明确了 // a: number // b: number // 返回值: number function sum(a, b){ return a + b; }
(3)减少了复杂的错误处理逻辑
/*** * 这个函数接收一个数字数组作为参数 * 返回这个数组中所有数字的和 * */ // function sum(arr){ // let result = 0; // arr.forEach(v => { // result += v; // }) // return result; // } function sum(arr){ // 首先判断用户是否有传递参数进来 if(!arr){ throw new Error("函数需要传参"); } if(!Array.isArray(arr)){ throw new Error("函数需要一个数组作为参数"); } if(!arr.every(v => typof v == 'number')){ throw new Error("函数需要的数组为数字数组!") } let result = 0; arr.forEach(v => { result += v; }) return result; } sum([1, 2, 3]); sum(100) sum(['a', 'b']) sum()
(4)适合使用IDE(集成开发环境),容易定位错误的赋值类型。
(5)便于代码重构
function test(num){ console.log(num) } test({name: "郭富城"}) test({name: "郭富城"}) test({name: "郭富城"}) test({name: "郭富城"})
-
静态类型的问题
- 增加代码量(需要写更多类型相关代码,较复杂)
- 需要花时间掌握类型
- 可能会降低开发效率
- 如何在
js
中使用静态类型1> Flow FaceBook 的开源技术
2> TypeScript 微软公司开发的语言
二、 Flow的基本使用
Flow is a static type checker for JavaScript 即:js
的静态类型检查工具
1、flow起步
(1)初始化package.json
npm init -y
补充:-f
(代表force)、-y
(代表yes)跳过提问阶段,直接生成一个新的package.json
(2)下载安装flow
npm install --save-dev flow-bin
补充:全局安装 : 将一个模块安装到系统目录中,各个项目都可以调用。一般来说,全局安装只适用于工具模块,比如
eslint
和gulpnpm install XXX -g`
本地安装 : 指的是将一个模块下载到当前项目的node_modules子目录,然后只有在项目目录之中,才能调用这个模块。
npm install XXX 与 npm install XXX --save (npm install XXX -S)
和
npm install XXX --production
,模块名将被添加dependencies
生产环境要用的;;
npm install XXX --save-dev (npm install XXX -D)
,模块名将被添加到devDependencies
开发要用的
(3)手动添加flow
使用npm run flow
需要在“scripts”中手动添加"flow": "flow"
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"flow": "flow"
}
}
(4)执行以下命令,生成 .flowconfig
的空文件
npm run flow init
[ignore] //忽略检测哪些文件 默认检查项目目录下所有文件
[include] //检测哪些文件 所谓的项目目录其实是 .flowconfig 目录,.flowconfig 所在的目录就是一个 Flow 项目
[libs] //第三方库
[lints]
[options]
[strict]
2、flow使用基本语法
在flow中如果想要为一个数据添加类型var 变量: 数据类型 = 数据
;
想要flow检查那个文件,就需要给文件添加@flow标记,否则flow不会对文件进行类型检测
1、通过注释的方式进行添加
(不会改写js
代码,代码在添加完类型之后仍然可以正常运行)
//@flow
var a /*: number*/ = 10;
a = "abc";
console.log(a);
执行命令:
npm run flow
类型检测结果:
通过注释方式添加的js
执行: node + 要进行检查的js文件
, js
代码正常运行。
2、使用babel进行转码(推荐)
通过直接给数据添加类型,改写了js
代码,js
代码运行会报语法错误,如果要正常运行,需要使用babel进行转码(推荐)
1)安装babel:
npm install babel-cli babel-preset-flow -D
2)在项目的根目录中创建一个.babelrc
文件:
{
"presets": ["flow"]
}
3)在package.json
的“scripts”中添加 "build": "babel src/ -d ./dist"
注释:把需要Babel进行编译的文件放到src
文件夹下,编译后的文件放到dist
文件夹下,-d表示目录。
{
"scripts": {
"build": "babel src/ -d ./dist"
}
}
最后运行:
//@flow
var a: number = 5;
function sum(x:number,i:number) {
return x + i;
}
sum(1,2);
//上面代码要正常运行的话,需要通过babel进行转码。
//------------------------------分割线----------------------------------------
// 执行`npm run build`后,代码被编译成-如下
var a = 5;
a = "abc";
function sum(x, i) {
return x + i;
}
sum(1, 2);
3、flow中的数据类型
//@flow
//number类型
//number类型可以赋值的内容为:数字,NaN, Infinity
let a: number = 100;
let b: number = NaN;
let c: number = Infinity;
//string类型
//number类型可以赋值的内容为:字符串
let str1: string = '12334'
//boolean 布尔类型
//void javascript中的undefined
//null js中的null
//Array 类型
//在声明数据为数组类型的时候,我们需要为数组制定元素的类型
let arr: Array<number> = [1,2,3];
//any 任意类型
let name: any = 123;
name = "123";
let arr2: Array<any> = [1,2,'3']
//Object 对象类型
function obj(o:{sayH: () => void}, name: string) {
o.sayH();
}
let o = {
name: '小明',
sayH() {
console.log("hello")
}
}
obj(o)
function ajx(option: {url: string, type: string, success: (data: Object)=> void}) {
}
ajx()
//--------------------------------------------分割线------------------------------------
//Function 函数类型
//@flow
function test(a: number, b:number): number {
return a + b;
}
// let d: string = test(1, 2);
//可以将变量声明为函数类型
//也就意味着我们可以指定为变量赋值的函数的类型
let func:(a: number, b:number) => number = test;
function ajc(callback:(data: Object) => void) {
}
ajc(function(obj: Object) {
})
//-------------------------------------------分割线-------------------------------------
//Maybe类型
//@flow
//Maybe类型相当于给数据添加了两个可能的类型null和void
function test(a: ?number) {
a = a || 0;
console.log(a);
}
test(10);
test();
//或操作
let a: number | string = 234;
a = '23'; //ok
a = true; //error
//类型推断
function test(a:number, b: number) {
return a + b;
}
let c: string = test(1,2); //error,推断函数返回number类型,与string不匹配;
4、简化错误处理代码
不使用flow:
/**
* 功能:传递一个数字数组,计算数组中所有数字的和并返回结果;
*/
function sum(arr) {
//是否有参数传入
if(!arr) {
throw new Error('此函数需要传递一个数组作为参数')
}
//传入参数是否是数组
if(!Array.isArray(arr)) {
throw new Error('此函数需要传递一个数组参数')
}
//传入参数是否是数字数组
if(!arr.every(v => typeof v === 'number')) {
throw new Error('此函数需要传递一个数组作为参数,数组中的元素需要全部为数字')
}
let result = 0;
arr.forEach(v => {
result += v;
})
return result;
}
sum([2,3]);
使用flow:
//@flow
function sum(arr: Array<number>) {
let result = 0;
arr.forEach(v => {
result += v;
})
return result;
}
sum([2,'3']);
结果:
三、 小结
Flow:
Flow is a static type checker for JavaScript 即:js
的静态类型检查工具;
给js
提供了静态类型检查的能力,其实就是为js
添加了一个编译过程;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。