如何在对象初始化时将属性值设为自身变量名(以JS枚举为例)
解决方法
以下几种方案可以满足你避免重复书写键值对的需求,同时符合ES6+、可同步重构、JSDoc识别等要求:
方案1:用Object.fromEntries快速生成(最简洁)
利用ES6+的Object.fromEntries将键数组直接转换为键值相等的对象,配合Object.freeze实现不可变,加上JSDoc标签让编辑器识别为枚举:
class AA { /** * @enum {string} */ static Color = Object.freeze( Object.fromEntries(['Red', 'Green', 'Blue'].map(key => [key, key])) ); }
- 核心优势:仅需维护一个键数组,完全避免重复书写键值对
- 同步重构:修改数组中的字符串时,使用编辑器的“更改所有匹配项”或重命名功能,可同步更新对象的键和值
- 调试友好:枚举值为字符串,调试时能直接看到有意义的名称
方案2:自定义辅助函数(复用性强)
如果需要多次创建这类枚举,封装一个辅助函数可以进一步简化操作:
/** * 创建键值相等的不可变枚举对象 * @param {string[]} keys 枚举键名列表 * @returns {Readonly<Record<string, string>>} */ const createEnum = (keys) => Object.freeze( Object.fromEntries(keys.map(key => [key, key])) ); class AA { /** * @enum {string} */ static Color = createEnum(['Red', 'Green', 'Blue']); }
- 优势:后续创建其他枚举只需调用
createEnum并传入键数组即可,逻辑复用性高 - 同样满足不可变、同步重构、JSDoc识别等所有需求
方案3:Proxy动态映射(接近你设想的写法)
如果想要更贴近你示例中“仅写键名,自动赋值为键名”的语法,可以用Proxy拦截属性访问,首次访问时自动赋值:
class AA { /** * @enum {string} */ static Color = Object.freeze(new Proxy({}, { get(target, prop) { if (typeof prop === 'string' && !(prop in target)) { target[prop] = prop; } return target[prop]; } })); }
- 注意:该方案的枚举键会在首次访问后才被添加到对象中,对自动补全的支持略有不足,适合不需要提前枚举所有键的场景
关键需求匹配说明
- 简化实现:方案1和2的代码量极少,无需繁琐的重复代码
- 同步重构:维护数组或变量时,编辑器的重命名功能可一次性同步所有键值
- JSDoc识别:添加
@enum标签后,VSCode会提供完整的枚举自动补全和类型提示 - 不可变性:所有方案都用
Object.freeze冻结对象,防止意外修改 - 调试友好:枚举值均为字符串,调试时能直观看到对应名称
内容的提问来源于stack exchange,提问作者Nor.Z
相关产品推荐
相关产品推荐

