乐趣区

关于前端:聊聊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 = 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) // 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"
}

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

<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) // 1
console.log(obj.B) // 8
console.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
}

感激

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

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

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

退出移动版