JaveScript语言类型

了解一种语言的优势和劣势 —— 通过参考大量信息,而不仅仅基于广告宣传或公众意见 —— 会让您可以更好地控制何时需要使用以及何时不能使用这种语言。

Posted by Azr on December 24, 2018

JavaScript是一种弱类型的,动态类型检查的语言,JavaScript具有动态类型的检查特征。

弱类型

在定义变量的时候,我们可以为变量赋值任何数据,变量的数据类型不是固定死的,这样的类型叫做弱类型。

弱类型语言是指一个变量可以被赋值不同类型的数据。

var a = 10;

a = "abc";

a = [];

a = function(){};

强类型

在声明变量的时候,一旦给变量赋值,那么变量的数据类型就已经确定,之后如果要给该变量赋值其他类型的数据,需要进行强制数据类型转换。(不可更改)

int a = 10;

a = "10";

动态类型

动态类型的类型检查会在代码运行的时候进行。

var obj = {};

obj.forEach(function(v,i) => {

})

forEach是数组才有的方法,会进行报错,是在运行的时候进行报错。

静态类型

而静态类型的类型检查则是在编译时进行。

int num = 100;

num = "abc";

Java是强类型语音,在编译的时候会进行报错。


当出现一个类型错误时,静态类型检查和动态类型检查的差异就凸显出来了。

在静态类型语言中,类型检查发生在编译阶段。

在动态类型语言中,只有在程序运行了一次的时候错误才会被发现,也就是在运行时。

动态类型可能会带来的问题

  1. 动态类型,类型检查的操作是在运行时进行的。

    由于JS是动态类型语言,没有编译的环节,所有的类型检查是在代码运行时进行的,这就意味着我们书写的代码中的某些错误,只能在代码运行时在会被发现。

    var n1 = 123;
    var n2 = 456;
    function sum(a,b){ 
    	return a+b;
    }
       
    console.log(sum(n1,n2)); //789
       
    console.log(sum('aaa',1));// aaa1
    
  2. 代码中的错误,只能在代码运行的时候被发现。

    function greet(obj) {
           
    // 这句代码,我们尝试去调用了obj的sayHello方法
    // 在编码阶段,我们无法确定最终传进来的参数对象究竟是什么
    // 只有在代码实际运行阶段,执行到本句代码的时候
    // 才会发现传入的obj对象根本没有sayHello方法,最终在运行阶段报错
           
        obj.sayHi();
    }
       
    var o = {
        name: 'MI'
    };
       
    greet(o);
    

    当然,动态类型带来的并不只是问题,它的灵活程度和编码成本相较于静态类型的语言来讲是显而易见的。比如在Java和C#被类型限制的生活不能自理的同学,在JS中你几乎可以放飞自我,为所欲为(Just a joke)。

静态类型的优势

  1. 提早发现代码中的Bug

    静态类型检查允许我们在程序没有运行之前就可以确定我们所设定的确定性是否是对的。一旦有违反这些既定规则的行为,它能在运行之前就发现,而不是在运行时。

    因为类型检查器会在你编码的时候就告诉你错误,所以这也就比你把代码交付到客户手中才发现一些错误要更方面(或者说付出更少的开发与维护成本)。

    function greet(obj) {
        obj.sayHi();
    }
       
    var o = {
        name: 'MI'
    };
       
    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. 促进更可靠的重构

    假设要进行代码重构,我们需要将函数的某个参数进行修改,那么在之前修改的时候我们可能需要犹豫,因为指不定项目中某个地方调用没有进行修改,那么运行的时候会产生奇怪的问题。而有了静态类型检测之后,类型检测会自动告诉我们修改后的代码哪里存在问题,我们只需要按照提示修复即可。

    function test(num){
       
        console.log(num)
       
    }
       
    test({name: "MI"})
       
    test({name: "MI"})
       
    test({name: "MI"})
       
    test({name: "MI"})
       
    
  5. 增强IDE的功能

    静态类型会增加IDE的更能,提高开发效率。

    IDE—集成开发环境。e.g. WebStorm

静态类型的问题说明

  1. 会增加代码量
  2. 需要花时间掌握类型
  3. 可能会降低开发效率

如何在js中使用静态类型

  1. Flow: FaceBook的开源技术
  2. TypeScript: 微软公司开发的语言

本文首次发布于 Azr的博客, 作者 @azrrrrr ,转载请保留原文链接.

原文链接: http://amor9.cn/2018/12/24/js