一、js是一种弱类型、动态类型检查的语言。

  1. 弱类型:在定义变量时,可以为变量定义复制任何数据,变量的数据类型不是固定死的,这样的类型叫做弱类型。

    var a = 10;
    a = "abc";
    a = [];
    a = function() {};
  2. 强类型:在声明变量时,一旦给变量赋值,那么变量的数据类型就已经确定,之后如果要给该变量赋值其他类型的数据,需要进行强制数据类型转换。

    int a = 6;
    a = "10";
  3. 动态类型与静态类型的核心区别

     动态类型的类型检查是是在代码运行的时候进行的,静态类型的类型检查则是在编译时进行。
     运行时类型检查--->`js`: 动态类型,类型检查的操作是在运行时进行的; 
     代码中的错误,只能在代码运行的时候被发现。影响代码效率和稳定性。
  4. 静态类型的优势

    (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: "郭富城"})
  5. 静态类型的问题

    1. 增加代码量(需要写更多类型相关代码,较复杂)
    2. 需要花时间掌握类型
    3. 可能会降低开发效率
  6. 如何在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和gulp

npm 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

类型检测结果:
clipboard.png

通过注释方式添加的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表示目录。
clipboard.png

   {
       "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']);

结果:
clipboard.png

三、 小结

Flow:

Flow is a static type checker for JavaScript 即:js的静态类型检查工具;

js提供了静态类型检查的能力,其实就是为js添加了一个编译过程;


西葫芦
21 声望0 粉丝

积跬步至千里