【发布时间】:2016-10-29 06:00:30
【问题描述】:
我想在JS中定义一个类似枚举的结构,但是有两个要求:
- 这些值是只读的,即没有用户可以分配给它们。
- 值 (0, 1, 2, ...) 可以映射回名称(与 Java 的 name method 一样)
我知道创建这样的枚举的方法通常满足一个要求或另一个,而不是两者。
我试过了:
const MyEnum = {
a: 0,
b: 1,
c: 2
};
枚举本身是常量,但值仍然是可变的,我无法有效地将值映射回名称。
在 Typescript 中编写 enum 时,它会输出:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["a"] = 0] = "a";
MyEnum[MyEnum["b"] = 1] = "b";
MyEnum[MyEnum["c"] = 2] = "c";
})(MyEnum || (MyEnum = {}));
这可以双向映射,但仍然没有常量值。
我发现满足这两个要求的唯一选择是在类上使用 getter:
class MyEnum {
get a() {
return 0;
}
...
}
这种方法极大地限制了合法名称并且有很多开销,尤其是在不能很好内联(或不能)内联 getter 的浏览器中。
@Shmiddty suggested freezing an object:
const MyEnum = Object.freeze({
a: 0,
b: 1,
c: 2
});
这很好地满足了常量要求,但没有提供将值映射回名称的好方法。
我可以编写一个帮助器来构建反向映射,例如:
function reverseEnum(enum) {
Object.keys(enum).forEach(k => {
enum[enum[k]] = k;
});
}
但是,如果原始对象被冻结或实际上是不变的,任何生成反向映射的编程解决方案都会遇到问题。
在 JS 中是否有一个干净、简洁的解决方案?
【问题讨论】:
-
为什么不创建枚举,添加反向属性,然后然后冻结它?尽管如此,我可以理解简洁地做到这一点的愿望。
-
@apsillers 这是个好主意。定义一个普通的 const 枚举对象,然后运行一个设置反向映射并冻结的助手。我可以很容易地保持一个电话,所以效果很好。想把它变成答案吗?
-
是否还需要传递的具体值?我可能也会用
Symbol包装所有值,但我不知道你在期待什么。通常枚举值实际上并不重要,至少在我编写的代码中。 -
const MyEnum = Object.freeze(reverseEnum({…}))似乎运作良好,不是吗? -
你可以在构造函数的末尾冻结
this。
标签: enums ecmascript-6