前言

什么是枚举,顾名思义咱们看到枚举这个词,脑子里就曾经想到这是一个键值对的模式,就可以看做是咱们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 = 4desktop = 5

注意事项 - 枚举对象递增

  • 枚举对象成员递增值为1
  • 枚举对象成员递增只会看以后值的前一个枚举成员是否有值,有值的话前面顺次跟着递增。跟第一个枚举成员值无关

数字枚举对象会存在反向映射

enum device {      phone      notebook,      desktop}

通过下面栗子咱们能够晓得,device.notebook = 1。但还能够通过device[1]获取进去notebook,这就是因为存在反向映射(key和value能够相互拜访)。

须要留神的是,只有数字枚举成员才会有反向映射,字符串或其它值是没有的。

来看下枚举对象被编译后的

<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fd33df8cc99f4517907ffa807af4f973~tplv-k3u1fbpfcp-watermark.image" width="100%"/>

咱们再来看一个问题

enum device {    phone = 2,    notebook = 1,    desktop}console.log(device.phone) // 2console.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"}

咱们来看一下编译后的代码

<img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bc0e79c440bf4efc99c404019ea3abed~tplv-k3u1fbpfcp-watermark.image" width="100%"/>

能够看到下面编译后的代码没有反向映射的代码。

字符串枚举是没有递增的,以后的枚举成员前一个值为字符串,那么以后的枚举对象如果不赋值就会报错。

enum device {    phone = "1",    notebook}

下面这种状况就会导致编译阶段报错。"枚举成员必须具备初始化表达式",待会咱们就会讲到枚举对象的表达式

异构枚举

异构枚举是啥呢,直白的说就是一个枚举对象中能够包含数字枚举成员字符串枚举成员,就是能够混合应用。然而咱们要正儿八经的应用枚举对象的话,个别还真不会应用异构枚举,就像文档说的一样,仿佛你并不会这么做。

enum Person {    name = "前端娱乐圈",    age = 18}

在看一个栗子

enum Person {    name = "前端娱乐圈",    age = 3 * 6}

下面这种是会报错的,“含字符串值成员的枚举中不容许应用计算值”,枚举对象成员有字符串的则不能再设置其它枚举对象成员为计算的值(3 * 6)。然而能够间接写字面量的。上面咱们会讲到计算

计算的和常量成员

枚举对象中的枚举成员都带有一个值,这个值是计算的常量。那么怎么看是计算的还是常量呢。这就讲到咱们下面说的枚举对象成员表达式,只有是表达式那肯定就是常量否则就是计算的。所以只须要晓得枚举成员是表达式就晓得它就是常量。

当满足上面其中一个条件那么它就是一个表达式。以下借用官网的规定条件

  • 一个枚举表达式字面量(次要是字符串字面量或数字字面量)
  • 一个对之前定义的常量枚举成员的援用(能够是在不同的枚举类型中定义的)
  • 带括号的常量枚举表达式
  • 一元运算符 +, -, ~其中之一利用在了常量枚举表达式
  • 常量枚举表达式做为二元运算符 +, -, *, /, %, <<, >>, >>>, &, |, ^的操作对象。 若常数枚举表达式求值后为 NaNInfinity,则会在编译阶段报错。

下面这些条件成立之后那么以后枚举成员就是一个常量。常量就是能够在编译阶段求值的

常量

enum obj {    index, // 满足条件 常量    index1 = index, // 满足条件 常量    age = 2 << 1, // 满足条件 常量     num = 30 | 2, // 满足条件 常量    num1 = 10 + 29 // 满足条件 常量}

在看一下下面编译后的代码,能够看到间接在编译阶段求值了。

<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/42beb700d9cd4d0a81d756d12384910b~tplv-k3u1fbpfcp-watermark.image" width="100%"/>

计算的

enum obj {    nameLen = "前端娱乐圈".length, // 计算的    num = Math.random() * 100 // 计算的}

在看一下计算的编译后的代码是没有求值的。

<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b517b83eba894ce88c1973b77478f37f~tplv-k3u1fbpfcp-watermark.image" width="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) // 1console.log(obj.B) // 8console.log(obj.C) // 0

那么下面这个栗子,编译后只能看见console.log这些值。

<img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c34317c5a0c54d8a8ac34f9823c16a21~tplv-k3u1fbpfcp-watermark.image" width="100%"/>

内部枚举

内部枚举应用declare关键字定义,文档形容:内部枚举用来形容曾经存在的枚举类型的形态,意思就是说内部枚举用来形容以后环境中存在的枚举对象。内部枚举和一般枚举的一个区别就是,在内部枚举外面没有初始化的枚举成员会当成一个计算值,而在一般枚举外面则是一个常量

declare enum Enum {    A = 1,    B,    C = 2}console.log(Enum);console.log(Enum.A)

下面这种执行完,你会发现不论执行枚举自身还是枚举成员都是报错,"Enum is not defined"。因为内部枚举编译后压根就没有生成。所以有明确内部枚举用处的小伙伴给解答一下,谢谢啦~

枚举成员的类型

枚举成员也能够被当做一个类型,就是能够指定某些变量的值必须是枚举成员的值。

枚举成员成为类型必须满足其中之一条件

  • 字面量枚举成员是指不带有初始值的常量枚举成员
  • 任何字符串字面量(如:AB
  • 任何数字字面量(如: 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}

感激

谢谢浏览,如有帮忙请点个关注、珍藏吧

感觉有帮忙能够关注 前端娱乐圈 公众号,每天为你推送一篇小常识

大家也能够加我 微信 交个敌人,能够找我聊天或拉你进技术交换群