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
:追求性能优化、代码精简,且无需运行时枚举逻辑。