使用Object.freeze()后,如何实现状态枚举双向映射以获取键名?
解决冻结对象的双向枚举访问问题
你遇到的问题和Object.freeze()无关,核心原因是你定义的AnimeState只有「键→值」的单向映射,没有添加「值→键」的反向映射关系,所以用值去访问时找不到对应的键名。
先修正代码语法错误
你原代码里Idle = 1的写法不符合对象语法,键值对应该用冒号:分隔,正确的基础定义如下:
const baseAnimeState = { Idle: 1, Walking: 2, Running: 3, Attacking: 4, Dead: 0, Uninitialized: -1 };
实现双向映射+对象冻结的方案
要兼顾双向访问和对象冻结,只需先给对象添加反向映射属性,再执行冻结操作即可:
方案1:手动构建双向映射
// 1. 定义基础键值映射 const baseAnimeState = { Idle: 1, Walking: 2, Running: 3, Attacking: 4, Dead: 0, Uninitialized: -1 }; // 2. 构建双向映射:给对象添加「值→键」的反向属性 const AnimeState = {...baseAnimeState}; for (const [key, value] of Object.entries(baseAnimeState)) { AnimeState[value] = key; } // 3. 冻结对象,防止后续意外修改 Object.freeze(AnimeState); // 测试双向访问 this.state = AnimeState.Uninitialized; console.log(AnimeState[this.state]); // 输出"Uninitialized" console.log(AnimeState["Running"]); // 输出3
方案2:封装通用枚举生成函数
如果需要多次创建这类双向枚举,可以封装工具函数提升复用性:
function createBidirectionalEnum(enumObj) { const result = {...enumObj}; for (const [key, val] of Object.entries(enumObj)) { // 校验值的唯一性,避免反向映射被覆盖 if (result[val]) { console.warn(`枚举值${val}重复,键${key}的反向映射会覆盖已有键${result[val]}`); } result[val] = key; } return Object.freeze(result); } // 使用函数创建枚举 const AnimeState = createBidirectionalEnum({ Idle: 1, Walking: 2, Running: 3, Attacking: 4, Dead: 0, Uninitialized: -1 }); // 测试双向访问 this.state = AnimeState.Uninitialized; console.log(AnimeState[this.state]); // 输出"Uninitialized"
注意事项
- 务必保证枚举的值是唯一的,若多个键对应同一个值,后添加的反向映射会覆盖前面的,导致部分键名无法通过值获取。
Object.freeze()仅禁止修改对象属性,不会影响已存在属性的正常访问,因此提前构建好双向映射后,冻结状态依然支持双向访问。
内容的提问来源于stack exchange,提问作者Alix Blaine
相关产品推荐
相关产品推荐

