深入理解TS(7)—— TS枚举

avatar

TS枚举.png

TS枚举

枚举的作用

在实际编程过程中,一些数据的取值往往是有限的,如表示周日期的数据。对于这些数据我们可以使用枚举来限制类型。

enum Week{
    Mon = 1, //1
    Tues, //2
    Wed, //3
    Thur, //4
    Fir, //5
    Sat, //6
    Sun //7
}

枚举相对于联合类型

从枚举的作用可以看出,枚举常常用于为取值有限的基本类型数据做类型注解。但是TS的联合类型也可以提供相同的作用。

let a: 1 | 2 | 3 | 4 | 5 | 6 | 7;

enum weeklyDate{
    Mon = 1,
    Tues,
    Wed,
    Thur,
    Fir,
    Sat,
    Sun
}

let b =  weeklyDate.Mon
  • 枚举相对联合类型的好处

    • 枚举支持添加行内注释,这种注释会被ide识别,并可以在使用的时候看到。

      enum weeklyDate{
          /** 周一 */
          Mon = 1,
          /** 周二 */
          Tues,
          Wed,
          Thur,
          Fir,
      }
      let b =  weeklyDate.Tues
      

截屏2022-07-05 下午5.57.41.png - 当需要修改有限取值的变量可能的取值时,使用枚举时,只需要修改一次,也就是可以统一进行值变更。

  • 枚举相对联合类型的不足

    • 枚举在经过编译后会产生额外的代码。
    • 开发时需要额外定义枚举类型声明,有导入和导出场景,可能需要处理标识符冲突。

使用场景

  • 枚举的使用场景

    • 对于可能会经常进行值变更的变量或需要依赖行内注释解释的场景。
  • 联合类型的使用场景

    • 对于不需要经常进行值变更的变量,以及变量取值含义明确不太依赖注释的场景。

常用的枚举

数字类型枚举

  • 枚举成员的值都是number类型

    • 数字类型枚举在不指定枚举值时,默认从0开始自增。

      enum weeklyDate{
          Mon,
          Tues,
          Wed,
          Thur,
          Fir,
      }
      let p = weeklyDate.Mon
      console.log(p) //0
      
    • 如果只为数字类型枚举的第一个枚举成员指定枚举值,那么剩下的枚举成员的枚举值将从这个指定值开始自增。

      enum weeklyDate{
          Mon = 1,
          Tues,
          Wed,
          Thur,
          Fir,
      }
      
      let b =  weeklyDate.Mon
      console.log(b) //1
      
    • 也可以为每个枚举成员都制定一个值。

  • 被声明为数字类型枚举的变量可以接受其他数字类型的数据,也就是类型为数字类型枚举成员的变量可以被重新赋值另一个数字。

    enum weeklyDate{
        Mon = 1,
        Tues,
        Wed,
        Thur,
        Fir,
    }
    
    let p = weeklyDate.Mon
    p = 2 //不会报错
    
  • 数字类型枚举编译出的JS代码 编译前

enum Week{
    Mon = 1,
    Tues,
    Wen,
    Thur,
    Fri,
    Sat,
    SUn
}

编译后

var Week;
(function (Week) {
    Week[Week["Mon"] = 1] = "Mon";
    Week[Week["Tues"] = 2] = "Tues";
    Week[Week["Wen"] = 3] = "Wen";
    Week[Week["Thur"] = 4] = "Thur";
    Week[Week["Fri"] = 5] = "Fri";
    Week[Week["Sat"] = 6] = "Sat";
    Week[Week["SUn"] = 7] = "SUn";
})(Week || (Week = {}));

字符串类型枚举

  • 枚举成员的值都是字符串类型

    • 字符串类型枚举必须为每一个枚举成员指定枚举值,否则会被自动赋值为数字类型枚举。
  • 字符串类型枚举约束的变量不支持被重新赋值。

    enum WeekDate{
        Mon = 'Monday',
        Thue = 'Thuesday',
        Wen = 'Wednesday',
        Thur = 'Thursday',
        Fri = 'Friday',
        Sat = 'Saturday',
        Sun = 'Sun'
    }
    
    let p2 = WeekDate.Mon
    p2 = 'Monday' //会报错
    
    
  • 字符串类型枚举编译出的JS代码 编译前

enum WeekDate{
    Mon = 'Monday',
    Thue = 'Thuesday',
    Wen = 'Wednesday',
    Thur = 'Thursday',
    Fri = 'Friday',
    Sat = 'Saturday',
    Sun = 'Sun'
}

编译后

var WeekDate;
(function (WeekDate) {
    WeekDate["Mon"] = "Monday";
    WeekDate["Thue"] = "Thuesday";
    WeekDate["Wen"] = "Wednesday";
    WeekDate["Thur"] = "Thursday";
    WeekDate["Fri"] = "Friday";
    WeekDate["Sat"] = "Saturday";
    WeekDate["Sun"] = "Sun";
})(WeekDate || (WeekDate = {}));

常量枚举

  • 在枚举关键字enum前加const关键字
const enum Week{
    Mon = 1,
    Tues,
    Wed,
}
let p1 = Week.Mon

数字类型枚举的相互映射

数字类型枚举的相互映射是指数字类型枚举支持使用枚举成员访问枚举值,也支持使用枚举值访问枚举成员。

常量枚举

常量枚举的优缺点

  • 优点

    • 常量枚举在编译后不会留下额外的JS代码。
    • 常量枚举将直接编译为枚举值,提高了性能。 非常量枚举
    enum Week{
        Mon = 1,
        Tues,
        Wed,
    }
    let p1 = Week.Mon
    

    编译为

    ...//枚举声明的编译结果
    let p = Week.Mon
    

    因此js引擎在执行这一句时,首先会对Week变量进行RHS查询,然后会查询Week变量中是否存在一个Mon属性。

    常量枚举

    const enum Week{
        Mon = 1,
        Tues,
        Wed,
    }
    let p1 = Week.Mon
    

    编译为

    let p = 1 //直接被赋值为对应的枚举值
    

    js引擎不需要进行两次RHS查询,因此可以提高性能。

  • 缺点

    • 转化为常量枚举的数字类型枚举不再有相互映射的特点。(这可以通过设置preserveConstEnums调整)。

常量枚举编译后的结果

编译前

const enum Week{
    Mon = 1,
    Tues,
    Wed,
}
let p1 = Week.Mon

编译后

var p1 = 1 /* Mon */;

p1直接被赋值为对应的枚举值。