1. 编译方式
-
普通
enum编译时会生成一个运行时对象,将枚举名称和值双向映射。例如:
typescriptenum Direction { Up = 'UP', Down = 'DOWN', }编译为:
javascriptvar Direction; (function (Direction) { Direction["Up"] = "UP"; Direction["Down"] = "DOWN"; })(Direction || (Direction = {}));运行时可以通过
Direction.Up或Direction["Up"]访问值。 -
const enum完全在编译阶段被内联替换,不会生成任何运行时对象。例如:
typescriptconst enum Direction { Up = 'UP', Down = 'DOWN', } console.log(Direction.Up);编译为:
javascriptconsole.log("UP"); // 直接替换为字面量若启用
preserveConstEnums选项,会生成对象但不影响内联行为。
2. 运行时存在性
- 普通
enum
生成的枚举对象在运行时存在,支持动态访问(如Object.keys(Direction))。 const enum
默认不存在于运行时(除非启用preserveConstEnums),无法动态访问或反射。
3. 性能
- 普通
enum
运行时需查找对象,可能存在轻微性能开销。 const enum
直接替换为字面量,无运行时开销,适合高频使用的场景。
4. 成员值的限制
-
普通
enum-
允许常量成员(如字符串、数字字面量)和计算成员(如函数返回值)。
-
支持延迟求值(引用其他成员):
typescriptenum NormalEnum { A = 1, B = A * 2, // 允许,B = 2 }
-
-
const enum-
所有成员必须是常量表达式(无法使用计算值):
typescriptconst enum ConstEnum { A = 1, B = A * 2, // 允许,因为 A 是常量 // C = Math.random(), // 错误:必须是常量 }
-
5. 使用场景
-
普通
enum- 需要运行时动态访问或反射(如遍历成员)。
- 需要跨模块或环境声明。
- 支持声明合并(多次声明合并为一个)。
-
const enum- 追求极致性能或减少代码体积。
- 无需运行时枚举对象(如仅静态类型检查)。
6. 调试
- 普通
enum
运行时对象可见于调试工具,便于检查。 const enum
被内联为字面量,调试时无法查看原始枚举结构。
7. 跨模块与编译选项
-
普通
enum无需特殊处理即可跨文件使用。
-
const enum- 若跨模块使用,需确保编译配置正确(如
isolatedModules下可能需启用preserveConstEnums)。 - 内联值的替换依赖编译时的类型信息。
- 若跨模块使用,需确保编译配置正确(如
8. 示例对比
-
普通
enum的灵活性:typescriptenum LogLevel { Error = 0, Warn = 1, Info = calculateInfoLevel(), // 允许计算成员 } -
const enum的内联优化:typescriptconst enum HttpCode { OK = 200, NotFound = 404, } // 编译后:console.log(200); console.log(HttpCode.OK);
总结表格
| 特性 | 普通 enum |
const enum |
|---|---|---|
| 运行时对象 | 生成 | 默认不生成(可配置保留) |
| 性能 | 动态查找,稍慢 | 内联替换,更快 |
| 成员类型 | 允许常量和计算值 | 仅允许常量表达式 |
| 动态访问 | 支持(如 Object.keys()) |
不支持 |
| 跨模块/文件 | 直接支持 | 需配置支持 |
| 调试友好性 | 是 | 否(仅见字面量) |
| 适用场景 | 需要运行时逻辑或反射 | 高频使用、追求性能与代码简洁 |
何时选择?
- 选 普通
enum:需要运行时枚举对象、动态访问、计算成员或环境声明。 - 选
const enum:追求性能优化、代码精简,且无需运行时枚举逻辑。