- crm开发定制枚举的作用是列举类型crm开发定制中包含的各个值,crm开发定制一般用它来管理多个相同系列的常量(crm开发定制即不能被修改的变量),crm开发定制用于状态的判断。crm开发定制这是一种无序的数据结构,crm开发定制把键映射到值上,可以理解为编译时键固定的对象,访问键时,ts将检查指定的键是否存在
在web中,比较常见的状态判断有响应状态的判断:
const handleResponseStatus = (status: number): void => { switch (status) { case 200: // 请求成功时 // Do something... break; case 400: // 请求失败时 // Do something... break; default: throw (new Error('No have status code!')); }};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
刚刚的200,等都是没有争议的状态码,但是实际开发过程中往往后台人员会自己定义一些字符串标识状态:
- 接手项目的程序员不去翻阅文档的话根本不知道这是啥玩意
- 容易造成魔鬼字符串的问题
- 用enum可以很好地解决这个问题
enum requestStatusCodes { error = '400', success = '200',}enum requestWrongCodes { missingParameter = 'A', wrongParameterType = 'B', invalidToken = 'C'}const handleWrongStatus = (status: string): void => { // 如果觉得 requestWrongCodes.missingParameter 太长了,也可以用以下方式: const { missingParameter, wrongParameterType, invalidToken, } = requestWrongCodes; switch (status) { case missingParameter: // Do something... break; case wrongParameterType: // Do something... break; case invalidToken: // Do something... break; default: throw (new Error('No have wrong code!')); }};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 枚举分为两种:字符串到字符串之间的映射和字符串到数字之间的映射。即key和value反向对应的对象,如下所示:
enum Language { //枚举名称为大写的单数形式 English, //枚举中的键也为大写 Spanish, Russian}console.log(Language);//ts自动推导出来的Language如下{ '0': 'English', '1': 'Spanish', '2': 'Russian', English: 0, Spanish: 1, Russian: 2 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 枚举中的值使用点号或者方括号
let myFirstLanguage = Language.Englishlet mySecondLanguage = Language['Spanish']console.log(myFirstLanguage, mySecondLanguage); //0 1
- 1
- 2
- 3
- 一个枚举可以分成几次声明,ts会自动把各部分合并在一起,注意,如果分开声明枚举,ts只能推导出其中一部分的值,因此最好为枚举中的每个成员显式赋值
enum Language { English = 0, Spanish = 1,}enum Language { Russian = 2}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 不必为枚举中的所有成员都赋值,ts会尽其所能推导出缺少的值:
enum Language { English = 1, Spanish = 100 + 1, Russian //ts推导为102}console.log(Language);
- 1
- 2
- 3
- 4
- 5
- 6
- 枚举的值可以为字符串,甚至混用字符串和数字
enum Color { Red = '#c10000', Blue = '#007ac1', Pink = 'oxc10050', White = 255}let red = Color['Red']let white = Color.Whiteconsole.log(red, white); //#c10000 255
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- ts比较灵活,允许通过值访问枚举,也允许通过键访问枚举,不过容易导致问题
enum Language { English, Spanish, Russian,}console.log(Language[0], Language[1]); //English Spanish
- 1
- 2
- 3
- 4
- 5
- 6
Language[‘Chinese’]和 Language[6]明明都不存在,为什么前者报错后者不报错呢?
- 利用js实现enum
- 实现key-value的反向对应的对象
- 不可修改
const newEnum = (descriptions) => { const result = {} Object.keys(descriptions).forEach(description => { console.log(result[description] = descriptions[description]);//注意,等号这个会返回等于的值 result[result[description] = descriptions[description]] = description; }); return Object.freeze(result)}let responseCode = newEnum({ error: 400, success: 200})console.log(responseCode);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
可以看到,enum本质上是生成键值对双向映射的对象,所以访问color[6]按照obj的惯性,是不会报错的,之后返回undefined
其实Color[6]不存在,但是并不阻止你这么做。为了避免这种不安全的访问操作:
- 可以通过const enum指定使用枚举的安全子集。下面使用该方法重写前面的Language枚举
- const enum 不允许通过键反向查找,行为和常规的js对象很像
- 另外,默认不编译生成任何js代码(就像第八点生成的那个result对象),而是在用到枚举成员的地方内插对应的值,例如,把Lauguage.Spanish直接替换成1
- 使用const emun的好处,加入需要使用的enum特别多,那在执行时就会不停地使用 IIFE 产生 Object 将 Key 和 Value 绑定到 Object,会造成一些效率上的损失,也会增加内存,但是 const 并不会产生 Object ,也就不会有以上的问题。
- 就算到的 Enum 不多,判断时也需要一直从 Object 中找出对应的值,而如果是用 const 声明 Enum ,在编译成 JS 时就将声明的值直接放入判断中。
- const enum的内插行为带来的安全问题
- const enum内插值的行为在从其他人编写的TypeScript代码中导入const enum时可能导致安全问题:假如原作者在你编译TypeScript 代码之后更新了const enum,那么在运行时你使用的枚举与原作者的枚举指向的值可能不同,而TypeScript没有这么智能,无法得知这一变化。
- 使用const enum时请尽量避免内插,而且只在受自己控制的TypeScript程序中使用。不要在计划发布到NPM中的程序,或者开放给其他人使用的库中使用。
如果想为const enum生成运行时代码,在 tsconfig.json中把TSC选项preserveConstEnums设为true:
参考:
- 书籍-《typescript编程》