Javascript 中的枚举与 ES6

我正在用Javascript重建一个旧的Java项目,并意识到在JS中没有好的方法来做枚举。

我能想到的最好的是:

const Colors = {
    RED: Symbol("red"),
    BLUE: Symbol("blue"),
    GREEN: Symbol("green")
};
Object.freeze(Colors);

防止重新分配和冻结可防止键和值发生变异。我使用的是符号,所以它不等于 ,或者除了它本身之外的任何其他东西。constColorsColors.RED0

这个公式有问题吗?有没有更好的方法?


(我知道这个问题有点重复,但之前的所有Q / A都相当旧,ES6为我们提供了一些新功能。


编辑:

另一个解决方案,它处理序列化问题,但我认为仍然存在领域问题:

const enumValue = (name) => Object.freeze({toString: () => name});

const Colors = Object.freeze({
    RED: enumValue("Colors.RED"),
    BLUE: enumValue("Colors.BLUE"),
    GREEN: enumValue("Colors.GREEN")
});

通过使用对象引用作为值,可以获得与符号相同的防撞功能。


答案 1

这个公式有问题吗?

我没有看到任何东西。

有没有更好的方法?

我将这两个语句折叠为一个:

const Colors = Object.freeze({
    RED:   Symbol("red"),
    BLUE:  Symbol("blue"),
    GREEN: Symbol("green")
});

如果你不喜欢样板,比如重复调用,你当然也可以编写一个帮助器函数,从名称列表中创建相同的内容。SymbolmakeEnum


答案 2

虽然用作枚举值对于简单的用例来说效果很好,但为枚举提供属性会很方便。这可以通过使用 用作包含属性的枚举值来完成。SymbolObject

例如,我们可以为每个名称和十六进制值指定:Colors

/**
 * Enum for common colors.
 * @readonly
 * @enum {{name: string, hex: string}}
 */
const Colors = Object.freeze({
  RED:   { name: "red", hex: "#f00" },
  BLUE:  { name: "blue", hex: "#00f" },
  GREEN: { name: "green", hex: "#0f0" }
});

在枚举中包含属性可避免编写语句(并且在扩展枚举时可能会忘记 switch 语句的新情况)。该示例还显示了使用 JSDoc 枚举注释记录的枚举属性和类型。switch

平等与存在和存在一样按预期工作。Colors.RED === Colors.REDtrueColors.RED === Colors.BLUEfalse