zoukankan      html  css  js  c++  java
  • 理解Flow静态类型检查

    一、为什么在JavaScript中使用静态类型

      了解静态类型的最快方法是将其与动态类型进行对比。 有静态类型参数的语言被称为静态类型语言。 另一方面,有动态类型参数的语言被称为动态类型语言。核心区别是静态类型语言在编译时执行类型检查,而动态类型的语言在运行时执行类型检查。

      这里我们一个概念需要解释:“类型检查”是什么意思?

      首先,让我们看一下Java中的类型与JavaScript的对比。

      “类型”指定义的数据的类型。例如,在Java中,如果将“boolean”定义为:boolean result = true;这有一个正确的类型,因为boolean注解与赋值给result变量的值匹配,而不是一个整数或其他类型。

      另一方面,如果您尝试声明:boolean result = 123;这将无法编译,因为它的类型不正确。 它将result显式标记为boolean类型,但是却给他赋值一个整数“123”。

      JavaScript和其他动态类型语言具有不同的方法,允许上下文确定正在定义的数据类型:var result = true;

      长话短说:静态类型的语言要求您在使用之前声明数据类型。 动态类型的语言不是这样。 JavaScript隐射(不能确定的意思)数据类型,而Java会直接声明它。所以你可以看到,类型允许你指定常量,或逻辑断言及程序执行的条件。

      类型检查确保并强制你声明的变量的类型(常量,布尔值,数字,变量,数组,对象)与您指定的值相匹配。例如,您可能会指定“此函数总是返回一个字符串”。程序运行时,您可以放心地确定它将返回一个字符串。

      当类型错误发生时,静态类型检查和动态类型检查之间的差异最为重要。在静态类型语言中,错误发生在编译步骤中,即在编译时会出现类型错误。在动态类型语言中,只有执行程序后才会出现错误,错误发生在运行时

      这意味着使用动态类型语言(如JavaScript或Python)编写的程序可以编译,即使它包含会阻止脚本正常运行的类型错误。另一方面,如果静态类型语言(如Scala或C ++)编写的程序包含类型错误,则在错误修复之前将无法编译。

    二、为什么需要引入类型检查?

      JS作为一个弱类型语言,一个著名的黑点是它很容易就写出非常隐蔽的隐患代码,在编译期甚至运行时看上去都不会报错,但是可能会发生各种各样奇怪的和难以解决的bug。类型检查是当前动态类型语言的发展趋势,JS的强类型超集TypeScript已经有了相当的知名度,吸引了大量开发者的学习兴趣,并且大部分开发者计划继续了解或者使用。

      所谓类型检查,就是在编译期尽早发现(由类型错误引起的)bug,又不影响代码运行(不需要运行时动态检查类型),使编写js具有和编写Java等强类型语言相近的体验。它可以:

      1、使得大型项目可维护

      2、增加代码的可读性

      3、通常会有更好的IDE支持

    三、Flow是什么?

      Flow是一个由Facebook出品的JavaScript静态类型检查工具,它与Typescript不同的是,它可以部分引入,不需要完全重构整个项目,所以对于一个已有一定规模的项目来说,迁移成本更小,也更加可行。除此之外,Flow可以提供实时增量的反馈,通过运行Flow server不需要在每次更改项目的时候完全从头运行类型检查,提高运行效率。

      Flow和Typescript都是给Javascript增加类型检查的优秀解决方案,两者的简单对比如下:

      两者在代码语法上有大量相似的地方,除了对于一些数据类型的支持不一样,具体请查看Flow的文档。关于Flow和Typescript的比较,可以简单总结为:对于新项目,可以考虑使用TypeScript或者Flow,对于已有一定规模的项目则建议使用Flow进行较小成本的逐步迁移来引入类型检查。

    四、Flow 是如何做到类型检查的呢?

      在 C#/Java 等强类型语言中,所有的变量、属性、参数是需要对其定义类型的,也需要对函数的返回值进行类型定义。这样,在程序编译过程中,编译器就会进行类型检查,如果类型不匹配,将会终止编译。也就是说,变量存储的数据自始至终必须是一种类型、函数接收的变量类型也被固定,如果在调用函数时传递其它类型,编译会被中断。

      第一步:我们要模仿 C#/Java 之类的语言,在编码过程中对类型进行定义。举个例子:

    function getStringLength(str: string):number {
        const len: number = str.length;
        return len;
    }

      我们写了一段简单的根据 Flow 的规则,进行类型声明的代码。虽然看起来没有什么用,但可以简单讲述如何定义类型了。这个函数接收一个 string 类型的参数,参数名为 str,函数的返回值是 number 类型。定义了一个类型为 number 的常量 len,它的值为 str 的长度,并且将其返回。

      第二步:通过 Flow 提供的工具进行类型检查。如果有类型不匹配的地方,工具会提示错误。

      第三步:但是,发布到线上的代码是不能加类型声明的,因为这样不符合规范,浏览器也不认。所以,我们需要对源代码进行一次编译,将所有声明的类型去掉,像正常的 JS 代码一样了。上面的代码编译过后将会变成:

    function getStringLength(str) {
        const len = str.length;
        return len;
    }

    五、Flow的作用

      一个简单的demo如下。

      运行Flow命令flow,这个demo的运行结果如下图所示:

      对于需要使用 Flow 进行类型检查的 js 文件,在开头加入 @Flow 注释,即可引入Flow。通过demo可以看到,Flow可以帮助找出由于不合理的类型操作引起的错误,包括运算符操作,函数参数类型和返回值类型等。Flow也支持自定义类型声明,泛型声明等类型语言相关的操作。
      /* @flow */很重要,在文件中添加这段注释,告诉Flow,该文件是需要进行类型检测。

    六、类型检查工具对团队有什么好处?

      通过在一个Vue技术栈的实际业务项目中引入Flow,我们大致获得了这些收益:

    1. 几乎消灭了由函数数据类型引起的bug
    2. 无需额外的关于变量、参数、返回值类型的注释,可以让读者了解必要的附加信息
    3. 大量减少由于使用第三方库不当引起的类型错误
    4. 可以在CI系统中集成
    5. 工具链配置成本比较低,只需要很少的工作量即可达到这些效果

      关于类型检查工具,读者可能需要考虑的问题,回答如下表所示。

  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/goloving/p/8908282.html
Copyright © 2011-2022 走看看