When developing in Javascript, it seems useful especially for event systems to use enum-likes, but not string comparison for performance considerations (also because it doesn't protect against typos). How do you use Enums in JS? Should I switch to Typescript?
-
2\$\begingroup\$ This question looks like it applies to Javascript development generally, not just to games. So you may get answers faster by asking on our general programming sister site StackOverflow. In fact, you may find it's already been answered there. \$\endgroup\$– DMGregory ♦Jul 19, 2018 at 10:25
2 Answers
Use Symbols.
Symbols are unique. Even if you pass the same value to them, they won't be the same.
let MY_ENUM = Symbol(1);
let MY_ENUM2 = Symbol(2);
alert(MY_ENUM == MY_ENUM2); // false
So store these in an object. To make sure the enum you reveive in a function is of a certain type, just use the in
keyword.
let myEnumObj = {
MY_ENUM: Symbol(1)
};
function foo(bar) {
if (bar in myEnumObj) { ... }
}
-
\$\begingroup\$ The idea is that I'd use something like a set of enums (think token types) as an import directly, like if (token.type = tokens.PLUS)... And I'd get an error when typing in "tokens.PLOS", instead of "undefined" \$\endgroup\$ Jul 19, 2018 at 11:48
-
1\$\begingroup\$ @AlexMitan JavaScript is a dynamically typed language, so it's very difficult for the interpreter to recognize if an undefined variable or object property will always be undefined. You can usually only catch errors like this at runtime. \$\endgroup\$– PhilippJul 19, 2018 at 12:48
-
\$\begingroup\$ Make sure you use a triple equal sign (===) in comparison in JavaScript for both value and type comparison. \$\endgroup\$– ChadAug 22, 2018 at 17:45
-
\$\begingroup\$ @Chad in this case it's not necessary, since a symbol is always completely unique, even
Symbol(1) == Symbol(1)
returns false. So you'll need to pass the same one aroumd \$\endgroup\$– BálintAug 22, 2018 at 18:41 -
\$\begingroup\$ Fair enough, thank you for explaining! +1 \$\endgroup\$– ChadAug 22, 2018 at 20:11
I also use Symbols, and have implemented them in an object literal like below using a setter.
I am using the object key as the string description inside ()
for easier debugging, and throw an error if the key is invalid.
export default {
currentScreen: null,
SCREEN: {
TITLE_SCREEN: Symbol('TITLE_SCREEN'),
GAME_SCREEN: Symbol('GAME_SCREEN'),
PAUSE: Symbol('PAUSE'),
GAMEOVER_SCREEN: Symbol('GAMEOVER_SCREEN'),
},
set setScreen(key) {
if (key in this.SCREEN) {
this.currentScreen = this.SCREEN[key];
} else {
throw new TypeError(`${key} is invalid key for SCREEN object`);
}
},
}