Enums in Javascript with ES6

前端 未结 15 1838
青春惊慌失措
青春惊慌失措 2020-12-12 10:42

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 C         


        
相关标签:
15条回答
  • 2020-12-12 11:30

    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.

    0 讨论(0)
  • 2020-12-12 11:33

    Here is my approach, including some helper methods

    export default class Enum {
    
        constructor(name){
            this.name = name;
        }
    
        static get values(){
            return Object.values(this);
        }
    
        static forName(name){
            for(var enumValue of this.values){
                if(enumValue.name === name){
                    return enumValue;
                }
            }
            throw new Error('Unknown value "' + name + '"');
        }
    
        toString(){
            return this.name;
        }
    }
    

    -

    import Enum from './enum.js';
    
    export default class ColumnType extends Enum {  
    
        constructor(name, clazz){
            super(name);        
            this.associatedClass = clazz;
        }
    }
    
    ColumnType.Integer = new ColumnType('Integer', Number);
    ColumnType.Double = new ColumnType('Double', Number);
    ColumnType.String = new ColumnType('String', String);
    
    0 讨论(0)
  • 2020-12-12 11:34

    you can also use es6-enum package (https://www.npmjs.com/package/es6-enum). It's very easy to use. See the example below:

    import Enum from "es6-enum";
    const Colors = Enum("red", "blue", "green");
    Colors.red; // Symbol(red)
    
    0 讨论(0)
  • 2020-12-12 11:37

    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.

    0 讨论(0)
  • 2020-12-12 11:39

    Here is an Enum factory that avoids realm issues by using a namespace and Symbol.for:

    const Enum = (n, ...v) => Object.freeze(v.reduce((o, v) => (o[v] = Symbol.for(`${n}.${v}`), o), {}));
    
    const COLOR = Enum("ACME.Color", "Blue", "Red");
    console.log(COLOR.Red.toString());
    console.log(COLOR.Red === Symbol.for("ACME.Color.Red"));

    0 讨论(0)
  • 2020-12-12 11:40

    You could use ES6 Map

    const colors = new Map([
      ['RED', 'red'],
      ['BLUE', 'blue'],
      ['GREEN', 'green']
    ]);
    
    console.log(colors.get('RED'));
    
    0 讨论(0)
提交回复
热议问题