it-swarm.com.de

Aufzählungen in Javascript mit ES6

Ich erstelle ein altes Java in Javascript und habe festgestellt, dass es in JS keine gute Möglichkeit gibt, Enums zu erstellen.

Das Beste, was mir einfallen kann, ist:

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

Das const verhindert, dass Colors neu zugewiesen wird, und das Einfrieren verhindert, dass die Schlüssel und Werte geändert werden. Ich benutze Symbole, damit Colors.RED ist ungleich zu 0 oder irgendetwas anderes außer sich.

Gibt es ein Problem mit dieser Formulierung? Gibt es einen besseren Weg?


(Ich weiß, dass diese Frage ein bisschen wiederholt wird, aber alle vorherigen Fragen/Antworten sind ziemlich alt, und ES6 bietet uns einige neue Funktionen.)


EDIT:

Eine andere Lösung, die sich mit dem Serialisierungsproblem befasst, aber meines Erachtens immer noch Realm-Probleme hat:

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

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

Durch die Verwendung von Objektreferenzen als Werte erhalten Sie die gleiche Kollisionsvermeidung wie bei Symbolen.

97
Eric the Red

Gibt es ein Problem mit dieser Formulierung?

Ich sehe keine.

Gibt es einen besseren Weg?

Ich würde die beiden Aussagen zu einer zusammenfassen:

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

Wenn Sie das Boilerplate nicht mögen, wie die wiederholten Symbol Aufrufe, können Sie natürlich auch eine Hilfsfunktion makeEnum schreiben, die aus einer Liste von Namen dasselbe erzeugt.

100
Bergi

Während die Verwendung von Symbol als Aufzählungswert für einfache Anwendungsfälle in Ordnung ist, kann es nützlich sein, Aufzählungen Eigenschaften zuzuweisen. Dies kann durch die Verwendung von Object als Aufzählungswert mit den Eigenschaften erfolgen.

Zum Beispiel können wir jedem Colors einen Namen und einen hexadezimalen Wert geben:

/**
 * 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" }
});

Durch das Einschließen von Eigenschaften in die Aufzählung wird vermieden, dass switch -Anweisungen geschrieben werden müssen (und möglicherweise neue Groß-/Kleinschreibung in den switch-Anweisungen vergessen werden muss, wenn eine Aufzählung erweitert wird). Das Beispiel zeigt auch die Enum-Eigenschaften und -Typen, die mit der Annotation JSDoc-Enum dokumentiert sind.

Gleichheit funktioniert wie erwartet mit Colors.RED === Colors.RED als true und Colors.RED === Colors.BLUE ist false.

9
Justin Emery

Wie oben erwähnt, können Sie auch eine makeEnum() -Hilfsfunktion schreiben:

function makeEnum(arr){
    let obj = {};
    for (let val of arr){
        obj[val] = Symbol(val);
    }
    return Object.freeze(obj);
}

Benutze es so:

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");
}
6
tonethar

Überprüfen Sie wie TypeScript es macht . Grundsätzlich machen sie folgendes:

const MAP = {};

MAP[MAP[1] = 'A'] = 1;
MAP[MAP[2] = 'B'] = 2;

MAP['A'] // 1
MAP[1] // A

Verwenden Sie Symbole, frieren Sie Objekte ein, was immer Sie wollen.

5
givehug

Das ist mein persönlicher Ansatz.

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);

Sie können Enumify überprüfen, eine sehr gute und gut ausgestattete Bibliothek für ES6-Enums.

4
Emmanuel.B

Wenn Sie kein reines ES6 benötigen und TypeScript verwenden können, gibt es ein Nice enum:

https://www.typescriptlang.org/docs/handbook/enums.html

2
Chris Halcrow

Vielleicht diese Lösung? :)

function createEnum (array) {
  return Object.freeze(array
    .reduce((obj, item) => {
      if (typeof item === 'string') {
        obj[item] = Symbol(item)
      }
      return obj
    }, {}))
}
1