ES6只读枚举可以将值映射到名称 [英] ES6 read-only enums that can map value to name

查看:97
本文介绍了ES6只读枚举可以将值映射到名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在JS中定义类似枚举的结构,但有两个要求:

I would like to define an enum-like structure in JS, but have two requirements:


  1. 这些值是只读的,即,没有用户可以分配给他们。

  2. 可以将值(0,1,2,...)映射回名称(如Java的名称方法

  1. The values be read-only, i.e. no users can assign to them.
  2. The values (0, 1, 2, ...) can be mapped back into the names (as with Java's name method)

我知道创建这样的枚举的方法通常符合一个要求,而不是两者。

The methods I know to create enums like this typically meet one requirement or the other, not both.

我试过:

const MyEnum = {
  a: 0,
  b: 1,
  c: 2
};

枚举本身是常量,但值仍然是可变的,我无法将值映射回

The enum itself is constant, but the values are still mutable and I can't map values back to names efficiently.

在Typescript中编写枚举时,它会输出:

When writing an enum in Typescript, it outputs:

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["a"] = 0] = "a";
    MyEnum[MyEnum["b"] = 1] = "b";
    MyEnum[MyEnum["c"] = 2] = "c";
})(MyEnum || (MyEnum = {}));

这可以映射两种方式,但仍然没有固定值。

This can map both ways, but still doesn't have constant values.

我发现符合这两个要求的唯一选项是在类上使用getter:

The only option I've found that meets both requirements would be using getters on a class:

class MyEnum {
  get a() {
    return 0;
  }
  ...
}

此方法极大地限制合法的名称,并且有很多的开销,特别是在浏览器不能很好地嵌入getter(或不能)。

This method dramatically restricts the legal names and has a lot of overhead, especially in browsers that don't inline getters well (or can't).

@Shmiddty建议冻结一个对象

const MyEnum = Object.freeze({
  a: 0,
  b: 1,
  c: 2
});

这满足了常规的要求,但并没有提供将值映射到名称的好方法

This meets the constant requirement well, but doesn't provide a great way to map values back to names.

我可以编写一个帮助器来构建反向映射,如:

I could write a helper that builds the reverse mapping like:

function reverseEnum(enum) {
  Object.keys(enum).forEach(k => {
    enum[enum[k]] = k;
  });
}

但是,生成反向映射的任何类型的编程解决方案将遇到问题,如果原始对象被冻结或以其他方式实际上是不变的。

But any kind of programmatic solution to generate the reverse mapping will run into problems if the original object is frozen or otherwise actually constant.

JS中有没有一个干净简洁的解决方案?

Is there a clean, concise solution to this in JS?

推荐答案

我将使用地图,以便您的枚举值可以是任何类型,而不是将其强制为字符串。

I'd use a Map so that your enum values can be any type, rather than having them coerced into strings.

function Enum(obj){
    const keysByValue = new Map();
    const EnumLookup = value => keysByValue.get(value);

    for (const key of Object.keys(obj)){
        EnumLookup[key] = obj[key];
        keysByValue.set(EnumLookup[key], key);
    }

    // Return a function with all your enum properties attached.
    // Calling the function with the value will return the key.
    return Object.freeze(EnumLookup);
}

如果您的枚举是字符串,我也可能会更改一行:

If your enum is all strings, I'd also probably change one line to:

EnumLookup[key] = Symbol(obj[key]);

以确保枚举值正确使用。只使用一个字符串,你不能保证一些代码没有简单地传递一个正常的字符串,恰好与一个枚举值相同。如果您的值始终是字符串或符号,您还可以将Map简单地替换为简单对象。

to ensure that the enum values are being used properly. Using just a string, you have no guarantee that some code hasn't simply passed a normal string that happens to be the same as one of your enum values. If your values are always strings or symbols, you could also swap out the Map for a simple object.

这篇关于ES6只读枚举可以将值映射到名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆