enum 类型是对 JavaScript 标准数据类型的一个补充。 使用枚举类型可以为一组数值赋予友好的名字。

基本使用

  1. enum Direction {
  2. Up,
  3. Down,
  4. Left,
  5. Right
  6. }

这样就定义了一个数字枚举,他有两个特点:

  • 数字递增
  • 反向映射

枚举成员会被赋值为从 0 开始递增的数字,

  1. console.log(Direction.Up) // 0
  2. console.log(Direction.Down) // 1
  3. console.log(Direction.Left) // 2
  4. console.log(Direction.Right) // 3

枚举会对枚举值到枚举名进行反向映射,

  1. console.log(Direction[0]) // Up
  2. console.log(Direction[1]) // Down
  3. console.log(Direction[2]) // Left
  4. console.log(Direction[3]) // Right

如果枚举第一个元素赋有初始值,就会从初始值开始递增,

  1. enum Direction {
  2. Up = 6,
  3. Down,
  4. Left,
  5. Right
  6. }
  7. console.log(Direction.Up) // 6
  8. console.log(Direction.Down) // 7
  9. console.log(Direction.Left) // 8
  10. console.log(Direction.Right) // 9

手动赋值

定义一个枚举来管理外卖状态,分别有已下单,配送中,已接收三个状态。

  1. enum ItemStatus {
  2. Buy = 1,
  3. Send,
  4. Receive
  5. }
  6. console.log(ItemStatus['Buy']) // 1
  7. console.log(ItemStatus['Send']) // 2
  8. console.log(ItemStatus['Receive']) // 3

但有时候后端给你返回的数据状态是乱的,就需要我们手动赋值。
比如后端说 Buy 是 100,Send 是 20,Receive 是 1,就可以这么写,

  1. enum ItemStatus {
  2. Buy = 100,
  3. Send = 20,
  4. Receive = 1
  5. }
  6. console.log(ItemStatus['Buy']) // 100
  7. console.log(ItemStatus['Send']) // 20
  8. console.log(ItemStatus['Receive']) // 1

计算成员

枚举中的成员可以被计算,比如经典的使用位运算合并权限,可以这么写,

  1. enum FileAccess {
  2. Read = 1 << 1,
  3. Write = 1 << 2,
  4. ReadWrite = Read | Write,
  5. }
  6. console.log(FileAccess.Read) // 2 -> 010
  7. console.log(FileAccess.Write) // 4 -> 100
  8. console.log(FileAccess.ReadWrite) // 6 -> 110

看个实例吧,Vue3 源码中的 patchFlags,用于标识节点更新的属性。

  1. // packages/shared/src/patchFlags.ts
  2. export const enum PatchFlags {
  3. TEXT = 1, // 动态文本节点
  4. CLASS = 1 << 1, // 动态 class
  5. STYLE = 1 << 2, // 动态 style
  6. PROPS = 1 << 3, // 动态属性
  7. FULL_PROPS = 1 << 4, // 具有动态 key 属性,当 key 改变时,需要进行完整的 diff 比较
  8. HYDRATE_EVENTS = 1 << 5, // 具有监听事件的节点
  9. STABLE_FRAGMENT = 1 << 6, // 子节点顺序不会被改变的 fragment
  10. KEYED_FRAGMENT = 1 << 7, // 带有 key 属或部分子节点有 key 的 fragment
  11. UNKEYED_FRAGMENT = 1 << 8, // 子节点没有 key 的 fragment
  12. NEED_PATCH = 1 << 9, // 非 props 的比较,比如 ref 或指令
  13. DYNAMIC_SLOTS = 1 << 10, // 动态插槽
  14. DEV_ROOT_FRAGMENT = 1 << 11, // 仅供开发时使用,表示将注释放在模板根级别的片段
  15. HOISTED = -1, // 静态节点
  16. BAIL = -2 // diff 算法要退出优化模式
  17. }

字符串枚举

字符串枚举的意义在于,提供有具体语义的字符串,可以更容易地理解代码和调试。

  1. enum Direction {
  2. Up = "UP",
  3. Down = "DOWN",
  4. Left = "LEFT",
  5. Right = "RIGHT",
  6. }
  7. const value = 'UP'
  8. if (value === Direction.Up) {
  9. // do something
  10. }

枚举结合 << 位运算符