为何TypeScript中枚举迭代如此反直觉?求底层原因
根本原因解析
1. TypeScript数字枚举的双向映射特性
TypeScript的数字枚举会被编译成双向映射的JavaScript对象,同时保存正向和反向映射关系:
- 正向映射:枚举名称 → 对应数值(如
Direction.Down = -1) - 反向映射:枚举数值 → 枚举名称(如
Direction[-1] = "Down")
从你提供的编译后代码可以清晰看到这个逻辑:
var Direction; (function (Direction) { // 先赋值正向映射,再建立反向映射 Direction[Direction["Down"] = -1] = "Down"; Direction[Direction["Up"] = 1] = "Up"; })(Direction || (Direction = {}));
最终生成的Direction对象实际结构为:
{ "-1": "Down", "1": "Up", "Down": -1, "Up": 1 }
2. Object.values()的遍历顺序规则
JavaScript中Object.values()的遍历顺序有明确规则:
- 优先遍历所有可枚举的数字类型键,按数字大小升序排列(这里对应键
-1、1,对应的值是"Down"、"Up") - 再遍历所有可枚举的字符串类型键,按插入顺序排列(这里对应键
"Down"、"Up",对应的值是-1、1)
因此Object.values(Direction)的返回结果是["Up", -1, "Down", 1],这直接导致循环执行4次,输出顺序和你的预期完全不符。
3. 预期偏差的核心
你原本只期望遍历枚举的数值成员,但Object.values()会把双向映射的所有值(包括反向映射的名称字符串)全部取出,再结合JS对象的遍历顺序规则,最终出现了违背预期的输出。
内容的提问来源于stack exchange,提问作者Moritz
相关产品推荐
相关产品推荐

