Odbudowuję stary projekt Java w Javascript i zdałem sobie sprawę, że nie ma dobrego sposobu na wykonanie wyliczeń w JS.
Najlepsze, co mogę wymyślić, to:
const Colors = {
RED: Symbol("red"),
BLUE: Symbol("blue"),
GREEN: Symbol("green")
};
Object.freeze(Colors);
const
Utrzymuje Colors
przed przeniesiony i zamrażania zapobiega mutacji klucze i wartości. Używam symboli, więc Colors.RED
to nie jest równe 0
ani nic poza sobą.
Czy jest jakiś problem z tym preparatem? Czy jest lepszy sposób?
(Wiem, że to pytanie jest trochę powtórzone, ale wszystkie poprzednie pytania i odpowiedzi są dość stare, a ES6 daje nam nowe możliwości.)
EDYTOWAĆ:
Inne rozwiązanie, które rozwiązuje problem serializacji, ale moim zdaniem nadal ma problemy z dziedziną:
const enumValue = (name) => Object.freeze({toString: () => name});
const Colors = Object.freeze({
RED: enumValue("Colors.RED"),
BLUE: enumValue("Colors.BLUE"),
GREEN: enumValue("Colors.GREEN")
});
Używając odniesień do obiektów jako wartości, uzyskuje się takie samo unikanie kolizji, jak w przypadku symboli.
javascript
enums
ecmascript-6
immutability
symbols
Eric the Red
źródło
źródło
JSON.stringify()
. Nie można serializować / deserializowaćSymbol
.Odpowiedzi:
Nie widzę żadnego.
Złożyłbym te dwa stwierdzenia w jedno:
Jeśli nie podoba ci się standardowy szablon, na przykład powtarzające się
Symbol
wywołania, możesz oczywiście napisać funkcję pomocniczą,makeEnum
która utworzy to samo z listy nazwisk.źródło
Symbol.for
nie nie mają problemów cross-realm, jednak to ma zwykle problemu kolizji z nazw prawdziwie globalnym .enum => ({[Colors.RED]: "bright red", [Colors.BLUE]: "deep blue", [Colors.GREEN]: "grass green"}[enum])
).Chociaż użycie
Symbol
wartości wyliczenia jako wartości wyliczeniowej działa dobrze w prostych przypadkach użycia, może być przydatne nadanie właściwości wyliczeniom. Można to zrobić, używającObject
jako wartości wyliczenia zawierającej właściwości.Na przykład możemy podać
Colors
nazwę i wartość szesnastkową:Uwzględnienie właściwości w wyliczeniu pozwala uniknąć konieczności pisania
switch
instrukcji (i prawdopodobnie zapominania o nowych przypadkach do instrukcji przełączania, gdy wyliczenie jest rozszerzane). Przykład pokazuje również właściwości wyliczenia i typy udokumentowane za pomocą adnotacji wyliczenia JSDoc .Równość działa zgodnie z oczekiwaniami z
Colors.RED === Colors.RED
byciemtrue
iColors.RED === Colors.BLUE
byciemfalse
.źródło
Jak wspomniano powyżej, możesz również napisać funkcję
makeEnum()
pomocniczą:Użyj tego w ten sposób:
źródło
const makeEnum = (...lst) => Object.freeze(Object.assign({}, ...lst.map(k => ({[k]: Symbol(k)}))));
użyj go jakoconst colors = makeEnum("Red", "Green", "Blue")
To jest moje osobiste podejście.
źródło
Sprawdź, jak to robi TypeScript . Zasadniczo wykonują następujące czynności:
Używaj symboli, zamrażaj obiekty, cokolwiek chcesz.
źródło
MAP[MAP[1] = 'A'] = 1;
zamiastMAP[1] = 'A'; MAP['A'] = 1;
. Zawsze słyszałem, że używanie przypisania jako wyrażenia to zły styl. Jakie korzyści uzyskasz z lustrzanych zadań?MAP[MAP[1] = 'A'] = 1;
.x
jest prawidłową wartością EnumEnum[Enum[x]] === x
. Nie rozwiązuje żadnego z moich pierwotnych problemów, ale może być przydatny i niczego nie psuje.Jeśli nie potrzebujesz czystego ES6 i potrafisz używać Typescript, to ma ładne
enum
:https://www.typescriptlang.org/docs/handbook/enums.html
źródło
Możesz sprawdzić Enumify , bardzo dobrą i dobrze wyposażoną bibliotekę wyliczeń ES6.
źródło
Może to rozwiązanie? :)
Przykład:
źródło
Wolę podejście @ tonethar, z niewielkimi ulepszeniami i kopaniem w celu lepszego zrozumienia podstaw ekosystemu ES6 / Node.js. Mając tło po stronie serwera, wolę podejście stylu funkcjonalnego do prymitywów platformy, co minimalizuje rozdęcie kodu, śliskie nachylenie w dolinie cienia śmierci w zarządzaniu stanem dzięki wprowadzeniu nowych typów i wzrostów czytelność - wyjaśnia intencję rozwiązania i algorytm.
Rozwiązanie z TDD , ES6 , Node.js , Lodash , Jest , Babel , ESLint
źródło
Array.from(Object.assign(args))
nic nie robi. Możesz po prostu użyć...args
bezpośrednio.Oto moje podejście, w tym kilka metod pomocniczych
-
źródło
możesz również użyć pakietu es6-enum ( https://www.npmjs.com/package/es6-enum ). Jest bardzo łatwy w użyciu. Zobacz poniższy przykład:
źródło
Oto moja implementacja wyliczenia Java w JavaScript.
Uwzględniłem również testy jednostkowe.
źródło
Możesz użyć mapy ES6
źródło
const x = Object.freeze({key: 'value'})
zamiast tego, aby uzyskać coś, co wygląda i zachowuje się jak wyliczenie w ES6