聊聊TypeScript中枚举对象(Enum)
前言
什么是枚举,顾名思义我们看到枚举这个词,脑子里就已经想到这是一个键值对的形式,就可以看做是我们JavaScript
中的json
对象一样。在ts中声明枚举对象的关键字是使用enum
,枚举成员一但定义就不可改变了。下面来介绍一下ts中的枚举对象。
数字枚举
我们先来说一下数字枚举
, 一目了然,一看就知道数字枚举的成员都是number
类型的。下面我们来看看创建一个简单的枚举对象吧。
enum device {
phone,
notebook,
desktop
}console.log(device.phone) // 0
上面的值是
phone
0、notebook
1、desktop
2。只要定义了枚举对象,默认不赋值,那么当前的枚举对象里面第一个的值从0开始依次递增。
看下面栗子
enum device {
phone = 3,
notebook,
desktop
}
上面我们默认给
phone
赋值一个3
,那么下面两个值也会默认递增,会变成notebook = 4
、desktop = 5
。注意事项 - 枚举对象递增
- 枚举对象成员递增值为1
- 枚举对象成员递增只会看当前值的前一个枚举成员是否有值,有值的话后面依次跟着递增。跟第一个枚举成员值无关
enum device {
phone
notebook,
desktop
}
通过上面栗子我们可以知道,
device.notebook = 1
。但还可以通过device[1]
获取出来notebook
,这就是因为存在反向映射
(key和value可以互相访问)。需要注意的是,只有数字枚举成员才会有反向映射,字符串或其它值是没有的。来看下枚举对象被编译后的
文章图片
我们再来看一个问题
enum device {
phone = 2,
notebook = 1,
desktop
}console.log(device.phone) // 2
console.log(device[2]) // desktop
可以看到上面代码中,
device.phone = 2
,然后我们使用反向这种方式访问device[2]
却是desktop
。这是因为默认我们给phone
赋值为2
,然后又给notebook
赋值为1
,这时desktop
跟着上一个枚举成员(notebook)值去递增,所以这时2
已经被替换为desktop
了。这里需要注意,避免踩坑,ts是不会检查出来的重复的值。字符串枚举
看过了上面的数字枚举,再来看字符串枚举,显然就明白字符串枚举成员的值肯定都是
string
类型。字符串枚举对象是没有反向映射的。enum device {
phone = "1",
notebook = "2",
desktop = "3"
}
我们来看一下编译后的代码
文章图片
可以看到上面编译后的代码没有反向映射的代码。
字符串枚举是没有递增的,当前的枚举成员前一个值为字符串,那么当前的枚举对象如果不赋值就会报错。
enum device {
phone = "1",
notebook
}
上面这种情况就会导致编译阶段报错。"枚举成员必须具有初始化表达式",待会我们就会讲到枚举对象的
表达式
。异构枚举
异构枚举是啥呢,直白的说就是一个枚举对象中可以包括
数字枚举成员
和字符串枚举成员
,就是可以混合使用。但是我们要正儿八经的使用枚举对象的话,一般还真不会使用异构枚举,就像文档说的一样,似乎你并不会这么做。enum Person {
name = "前端娱乐圈",
age = 18
}
在看一个栗子
enum Person {
name = "前端娱乐圈",
age = 3 * 6
}
上面这种是会报错的,“含字符串值成员的枚举中不允许使用计算值”,枚举对象成员有字符串的则不能再设置其它枚举对象成员为
计算的值(3 * 6)
。但是可以直接写字面量的。下面我们会讲到计算
计算的和常量成员
枚举对象中的枚举成员都带有一个值,这个值是
计算的
或常量
。那么怎么看是计算的还是常量呢。这就讲到我们上面说的枚举对象成员表达式
,只要是表达式那一定就是常量
否则就是计算的
。所以只需要知道枚举成员是表达式就知道它就是常量。当满足下面其中一个条件那么它就是一个表达式。以下借用官方的规则条件
- 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
- 一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
- 带括号的常量枚举表达式
- 一元运算符
+
,-
,~
其中之一应用在了常量枚举表达式 - 常量枚举表达式做为二元运算符
+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
的操作对象。 若常数枚举表达式求值后为NaN
或Infinity
,则会在编译阶段报错。
常量
enum obj {
index, // 满足条件 常量
index1 = index, // 满足条件 常量
age = 2 << 1, // 满足条件 常量
num = 30 | 2, // 满足条件 常量
num1 = 10 + 29 // 满足条件 常量
}
【聊聊TypeScript中枚举对象(Enum)】在看一下上面编译后的代码,可以看到直接在编译阶段求值了。
文章图片
计算的
enum obj {
nameLen = "前端娱乐圈".length, // 计算的
num = Math.random() * 100 // 计算的
}
在看一下计算的编译后的代码是没有求值的。
文章图片
const枚举
一般情况下,普通枚举对象就可以满足我的需求,但是有些情况比如为了节省额外的开销和性能,我们可以选择使用常量枚举,常量枚举使用
const
关键字定义,它与普通枚举不同的时,它会在编译阶段删除该对象,且不能访问该枚举对象,只能访问该枚举对象成员。常量枚举的成员只能是常量枚举表达式,不可以使用计算值const enum obj {
A = 1,
B = 3 * 6,
C = 1 & 2
}console.log(obj) // 报错
需要注意上面这个常量枚举对象编译后的对象也是"空"的,系统自动删除
const enum obj {
A = 1,
B = 3 * 6,
C = 1 & 2
}console.log(obj.A) // 1
console.log(obj.B) // 8
console.log(obj.C) // 0
那么上面这个栗子,编译后只能看见
console.log
这些值。文章图片
外部枚举
外部枚举使用
declare
关键字定义,文档描述:外部枚举用来描述已经存在的枚举类型的形状,意思就是说外部枚举用来描述当前环境中存在的枚举对象。外部枚举和普通枚举的一个区别就是,在外部枚举里面没有初始化的枚举成员会当成一个计算值
,而在普通枚举里面则是一个常量
。declare enum Enum {
A = 1,
B,
C = 2
}console.log(Enum);
console.log(Enum.A)
上面这种执行完,你会发现不管执行枚举本身还是枚举成员都是报错,"Enum is not defined"。因为外部枚举编译后压根就没有生成。所以有明白外部枚举用途的小伙伴给解答一下,谢谢啦~
枚举成员的类型
枚举成员也可以被当做一个类型,就是可以指定某些变量的值必须是枚举成员的值。
枚举成员成为类型必须满足其中之一条件
- 字面量枚举成员是指不带有初始值的常量枚举成员
- 任何字符串字面量(如:
A
、B
) - 任何数字字面量(如:
1
,100
) - 应用了一元
-
符号的数字字面量(如:-1
,-100
)
enum obj {
name = "前端娱乐圈",
num = -100
}interface msg {
title: obj.name;
num: obj.num
}let json: msg = {
title: obj.name,
num: obj.num
}
感谢
谢谢阅读,如有帮助请点个关注、收藏吧
觉得有帮助可以关注 前端娱乐圈 公众号,每天为你推送一篇小知识
大家也可以加我 微信 交个朋友,可以找我聊天或拉你进技术交流群
推荐阅读
- 热闹中的孤独
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募
- 2020-04-07vue中Axios的封装和API接口的管理