引言
在 TS
中枚举(enum
)是一个比较常用的语法, 通俗来说, 枚举就是对一个对象的所有可能取到的值的集合, 枚举的定义方式与结构体和联合体相似, 其形式为:
ts
enum 枚举名{
标识符①[=整型常数],
标识符②[=整型常数],
...
标识符N[=整型常数],
也许你看到过下面这两种枚举(enum
)定义的方式:
ts
// 普通枚举
enum Color { Red, Green, Blue }
// 常量枚举(使用 const)
const enum Color { Red, Green, Blue }
那么问题来了, 这两种定方式有什么区别呢?
其实上面两种声明方式唯一的区别就在于编译结果上有所不同, 下面我们将对其展开简单说明, 对于
TS
枚举的基本使用, 语法这边就不展开讲解了
一、普通枚举
如下我们使用 普通枚举
的方式, 声明了一个枚举 Color
ts
// 普通枚举
enum Color { Red, Green, Blue }
下面我们可以在 Typescript 游乐场 来看下上面 TS
编译后的结果
从图中我们会发现 普通枚举
编译后的 JS
代码是会去创建一个对象 Color
, 然后往对象上添加一些列的值。这里我们可以在自己项目中测试下, 打印出 Color
看看它是长啥样的
如上图, 可以看出, 最终编译后生成的 Color
对象实际上是一组 key => value
以及 value => key
的一个映射表
ts
// 普通枚举
enum Color { Red, Green, Blue }
Color.Red // 0
Color[2] // "Blue"
对于普通枚举, 最终编译出来的就是一个普通的对象, 如上代码译出来的 Color
就是一个普通的对象, 之后 Color
是有可能被篡改的(尽管它们是只读的, 但我们依然是有办法修改的)
ts
// 普通枚举
enum Color { Red, Green, Blue }
Color.Blue; // 2
// Color 中属性都是只读的, 可通过 Object.defineProperty 进行修改
Object.defineProperty(Color, 'Blue', { writable: true, value: 666 });
Color.Blue; // 666
Color.Blue; // 666
二、常量枚举
那么相对于普通枚举(只使用 enum
进行声明), 常量枚举(使用 const
+ enum
进行声明)在编译结果上又有什么不一样呢?
如下我们使用 常量枚举
的方式, 声明了一个枚举 Color
ts
// 常量枚举(使用 const)
const enum Color { Red, Green, Blue }
const red = Color.Red
const red = Color.Green
下面我们可以在 Typescript 游乐场 来看下上面 TS
编译后的结果
从 TS
编译后的结果会发现, 常量枚举和普通枚举的差异还是很大的, 对于常量枚举会在 TS
编译期间被删除, 常量枚举的成员在使用的地方会被替换为对应的值
三、总结
- 普通枚举
enum A {...}
和常量枚举const enum A {...}
之间的区别主要在于TS
的编译结果上有所差别 - 普通枚举
enum A {...}
, 会将其编译为一个JS
对象, 对象内就是枚举成员和值的一个相互映射 - 常量枚举
const enum A {...}
, 编译后不会生成任何代码, 会删除TS
部分内容, 对于使用到的成员只会进行值的替换 - 由此可见, 使用
常量枚举
会有更好的性能, 避免额外的性能开销; 那么大部分情况下我们更推荐使用常量枚举, 那么问题来了我们什么时候使用普通枚举呢? 答案是俺也没找到答案😭😭😭😭