可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm rebuilding an old Java project in Javascript, and realized that there's no good way to do enums in JS.
The best I can come up with is:
const Colors = {
RED: Symbol("red"),
BLUE: Symbol("blue"),
GREEN: Symbol("green")
};
Object.freeze(Colors);
The const
keeps Colors
from being reassigned, and freezing it prevents mutating the keys and values. I'm using Symbols so that Colors.RED
is not equal to 0
, or anything else besides itself.
Is there a problem with this formulation? Is there a better way?
(I know this question is a bit of a repeat, but all the previous Q/As are quite old, and ES6 gives us some new capabilities.)
EDIT:
Another solution, which deals with the serialization problem, but I believe still has realm issues:
const enumValue = (name) => Object.freeze({toString: () => name});
const Colors = Object.freeze({
RED: enumValue("Colors.RED"),
BLUE: enumValue("Colors.BLUE"),
GREEN: enumValue("Colors.GREEN")
});
By using object references as the values, you get the same collision-avoidance as Symbols.
回答1:
Is there a problem with this formulation?
I don't see any.
Is there a better way?
I'd collapse the two statements into one:
const Colors = Object.freeze({
RED: Symbol("red"),
BLUE: Symbol("blue"),
GREEN: Symbol("green")
});
If you don't like the boilerplate, like the repeated Symbol
calls, you can of course also write a helper function makeEnum
that creates the same thing from a list of names.
回答2:
Also check Enumify, a very good and well featured library for ES6 enums.
Hope this will help somebody.
Best regards,
Emmanuel
回答3:
Check how TypeScript does it.
Basically they do the following:
const MAP = {};
MAP[MAP[1] = 'A'] = 1;
MAP[MAP[2] = 'B'] = 2;
MAP['A'] // 1
MAP[1] // A
Use symbols, freeze object, whatever you want.
回答4:
As mentioned above, you could also write a makeEnum()
helper function:
function makeEnum(arr){
let obj = {};
for (let val of arr){
obj[val] = Symbol(val);
}
return Object.freeze(obj);
}
Use it like this:
const Colors = makeEnum(["red","green","blue"]);
let startColor = Colors.red;
console.log(startColor); // Symbol(red)
if(startColor == Colors.red){
console.log("Do red things");
}else{
console.log("Do non-red things");
}
回答5:
If you don't need pure ES6 and can use Typescript, it has a nice enum
:
https://www.typescriptlang.org/docs/handbook/enums.html
回答6:
Maybe this solution ? :)
function createEnum (array) {
return Object.freeze(array
.reduce((obj, item) => {
if (typeof item === 'string') {
obj[item] = Symbol(item)
}
return obj
}, {}))
}
回答7:
Whilst using Symbol
as the enum value works fine for simple use cases, it can be handy to give properties to enums. This can be done by using an Object
as the enum value containing the properties.
For example we can give each of the Colors
a name and hex value:
/**
* 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" }
});
Including properties in the enum avoids having to write switch
statements (and possibly forgetting new cases to the switch statements when an enum is extended). The example also shows the enum properties and types documented with the JSDoc enum annotation.
Equality works as expected with Colors.RED === Colors.RED
being true
, and Colors.RED === Colors.BLUE
being false
.
回答8:
This is my personal approach.
class ColorType {
static get RED () {
return "red";
}
static get GREEN () {
return "green";
}
static get BLUE () {
return "blue";
}
}
// Use case.
const color = Color.create(ColorType.RED);
回答9:
you can also use es6-enum package (https://www.npmjs.com/package/es6-enum). It's very easy to use. See the example below
回答10:
You could use ES6 Map
const colors = new Map([
['RED', 'red'],
['BLUE', 'blue'],
['GREEN', 'green']
]);
console.log(colors.get('RED'));