1 定义
枚举 ( Enum ) 类型常用于限定取值在一定范围的场景,类似于 type 关键字约束基础字面量类型值的范围(详见)。
举例:一周的值被限定为七天
// 注意声明方式enum Week {Sun, Mon, Tue, Wed, Thu, Fri, Sat};console.log('enum Week =>', Week);
2 理解
2.1 原理
上述例子编译后结果为:
// 注意声明方式var Week;(function (Week) {Week[Week["Sun"] = 0] = "Sun";Week[Week["Mon"] = 1] = "Mon";Week[Week["Tue"] = 2] = "Tue";Week[Week["Wed"] = 3] = "Wed";Week[Week["Thu"] = 4] = "Thu";Week[Week["Fri"] = 5] = "Fri";Week[Week["Sat"] = 6] = "Sat";})(Week || (Week = {}));;console.log('enum Week =>', Week);
即:枚举成员会以枚举值(默认从 0 开始,顺序递增 1)和枚举名互为键值赋值给枚举对象。
最终
console.log('enum Week =>', Week);enum Week => {'0': 'Sun','1': 'Mon','2': 'Tue','3': 'Wed','4': 'Thu','5': 'Fri','6': 'Sat',Sun: 0,Mon: 1,Tue: 2,Wed: 3,Thu: 4,Fri: 5,Sat: 6}
2.2 枚举值手动赋值
可以对枚举值进行手动赋予初始值,如:
// 注意声明方式enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};console.log('enum Week =>', Week);
则未赋予初始值的会接着前一个枚举值顺序递增 1 ,如上述编译后:
// 注意声明方式var Week;(function (Week) {Week[Week["Sun"] = 7] = "Sun";Week[Week["Mon"] = 1] = "Mon";Week[Week["Tue"] = 2] = "Tue";Week[Week["Wed"] = 3] = "Wed";Week[Week["Thu"] = 4] = "Thu";Week[Week["Fri"] = 5] = "Fri";Week[Week["Sat"] = 6] = "Sat";})(Week || (Week = {}));;console.log('enum Week =>', Week);
❗注意:如果手动赋予初始值与顺序递增值重复,会产生值被覆盖的情况:
enum Week {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};console.log('enum Week =>', Week);
编译结果
// 注意声明方式var Week;(function (Week) {Week[Week["Sun"] = 3] = "Sun";Week[Week["Mon"] = 1] = "Mon";Week[Week["Tue"] = 2] = "Tue";Week[Week["Wed"] = 3] = "Wed";Week[Week["Thu"] = 4] = "Thu";Week[Week["Fri"] = 5] = "Fri";Week[Week["Sat"] = 6] = "Sat";})(Week || (Week = {}));;console.log('enum Week =>', Week);
最终打印后发现:Week[3] = "Sun" 被 Week[3] = "Wed" 覆盖。
console.log('enum Week =>', Week);enum Week => {'1': 'Mon','2': 'Tue','3': 'Wed', // 这里被覆盖了'4': 'Thu','5': 'Fri','6': 'Sat',Sun: 3,Mon: 1,Tue: 2,Wed: 3,Thu: 4,Fri: 5,Sat: 6}
手动赋值的其他情况:
- 手动赋予初始值可以为负数和小数,后续未赋值的仍会以顺序递增 1 ;
手动赋予初始值可以为字符串,但后续不能含有未赋值的枚举值;
// ERROR: Week.eight 枚举成员必须具有初始化表达式。enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat = 'sex', eight, };console.log('enum Week =>', Week);
// 注意声明方式enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat = 'sex', eight = 'eight'};console.log('enum Week =>', Week);
编译后
var Week;(function (Week) {Week[Week["Sun"] = 7] = "Sun";Week[Week["Mon"] = 1] = "Mon";Week[Week["Tue"] = 2] = "Tue";Week[Week["Wed"] = 3] = "Wed";Week[Week["Thu"] = 4] = "Thu";Week[Week["Fri"] = 5] = "Fri";Week["Sat"] = "sex";Week["eight"] = "eight";})(Week || (Week = {}));;console.log('enum Week =>', Week);
3 常数项与计算所得项
枚举值有两种类型:常数项 ( constant member ) 和计算所得项 ( computed member ) ;
一般情况下都是常数项居多,符合常数项的要求有:枚举值为数值,未被初始化的可通过前一项顺序递增(第一项默认为 0);
- 枚举值为带括号的常数表达式;
- 枚举值为
+, -, ~一元运算符的常数表达式或+, -, *, /, %, &, |, <<, >>等二元运算符的常数表达式;
其他情况为计算所得项,如前面的字符串值,或其他表达式。
// Sat 与 eight 为 计算所得项enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat = 'sex', eight = 'eight'.length};console.log('enum Week =>', Week);
4 常数枚举与外部枚举
常数枚举是使用
const enum定义的枚举,它与普通枚举的区别是:它会在编译阶段被删除,且不能包括计算所得项;// ERROR: 'eight'.length 含字符串值成员的枚举中不允许使用计算值。const enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat = 'sex', eight = 'eight'.length};console.log('enum Week =>', Week);
// 常数枚举,编译后被删除const enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};const weekend = [Week.Sat, Week.Sun];console.log('weekend => ', weekend);
编译后
; var weekend = [6 /* Sat */, 7 /* Sun */]; console.log('weekend => ', weekend);外部枚举是使用
declare enum声明的枚举,前面知道declare声明的仅能用于编译时类型检查,编译后会被删除,外部枚举同声明语句一样,常用于声明文件 .d.ts 中;// 外部枚举,与常数枚举不同它能使用计算所得项 declare enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat, eight = "eight"}; const weekend = [Week.Sat, Week.Sun]; console.log('weekend => ', weekend);编译后
; var weekend = [Week.Sat, Week.Sun]; // ReferenceError: Week is not defined console.log('weekend => ', weekend);也能同时使用常数枚举和外部枚举,如
declare const ...,编译结果与常数枚举const一样;
