Enum flags en JavaScript
-
06-07-2019 - |
Question
J'ai besoin d'émuler le type enum en Javascript et l'approche semble assez simple:
var MyEnum = {Left = 1; Right = 2; Top = 4; Bottom = 8}
Maintenant, en C #, je pourrais combiner ces valeurs comme ceci:
MyEnum left_right = MyEnum.Left | MyEnum.Right
et puis je peux tester si enum a une certaine valeur:
if (left_right & MyEnum.Left == MyEnum.Left) {...}
Puis-je faire quelque chose comme ça en Javascript?
La solution
En javascript, vous devriez pouvoir les combiner en tant que:
var left_right = MyEnum.Left | MyEnum.Right;
Les tests seraient alors exactement comme dans votre exemple de
if ( (left_right & MyEnum.Left) == MyEnum.Left) {...}
Autres conseils
Vous devez simplement utiliser les valeurs binaires :
var myEnum = {
left: 1,
right: 2,
top: 4,
bottom: 8
}
var myConfig = myEnum.left | myEnum.right;
if (myConfig & myEnum.right) {
// right flag is set
}
Plus d'infos:
Oui, l'arithmétique au niveau des bits fonctionne en Javascript. Vous devez être prudent avec cela, car Javascript ne possède que le type de données Number
, qui est implémenté en tant que type à virgule flottante. Toutefois, les valeurs sont converties en valeurs signées 32 bits pour les opérations au niveau du bit. Donc, tant que vous n'essayez pas d'utiliser plus de 31 bits, tout ira bien.
J'ai essayé de créer un exemple qui illustre un cas d'utilisation courant dans lequel on peut vouloir utiliser des énumérations de masque de bits pour contrôler la verbosité de journalisation. Cela illustre l'utilisation des opérations bit par bit de JavaScript: Voir sur JSFiddle
/*
* Demonstration of how a Flags enum can be simulated in JavaScript and
* Used to control what gets logged based on user passed value
*/
// A Flags Enum (sort-of)
var LogLevels = {
NONE: 0,
INFO: 1,
TRACE: 2,
DEBUG: 4,
WARN: 8,
ERROR: 16,
FATAL: 32
};
// Initialize
var currLogLevel = LogLevels.NONE;
// User Sets a log level
var logLevel = LogLevels.WARN;
// Convert the configured logLvel to a bit-masked enum value
switch (logLevel) {
case LogLevels.INFO:
currLogLevel = LogLevels.INFO | LogLevels.TRACE | LogLevels.DEBUG | LogLevels.WARN | LogLevels.ERROR | LogLevels.FATAL;
break;
case LogLevels.TRACE:
currLogLevel = LogLevels.TRACE | LogLevels.DEBUG | LogLevels.WARN | LogLevels.ERROR | LogLevels.FATAL;
break;
case LogLevels.DEBUG:
currLogLevel = LogLevels.DEBUG | LogLevels.WARN | LogLevels.ERROR | LogLevels.FATAL;
break;
case LogLevels.WARN:
currLogLevel = LogLevels.WARN | LogLevels.ERROR | LogLevels.FATAL;
break;
case LogLevels.ERROR:
case LogLevels.FATAL:
default:
currLogLevel = LogLevels.ERROR | LogLevels.FATAL;
}
// Example: log verbosity set to WARN, so this would NOT be logged
if ((currLogLevel & LogLevels.DEBUG) == LogLevels.DEBUG) {
console.log("log DEBUG");
}