Enum flags in JavaScript

2019-03-08 13:02发布

I need to emulate enum type in Javascript and approach seems pretty straight forward:

var MyEnum = {Left = 1; Right = 2; Top = 4; Bottom = 8}

Now, in C# I could combine those values like this:

MyEnum left_right = MyEnum.Left | MyEnum.Right

and then I can test if enum has certain value:

if (left_right & MyEnum.Left == MyEnum.Left) {...}

Can I do something like that in Javascript?

4条回答
smile是对你的礼貌
2楼-- · 2019-03-08 13:41

You just have to use the bitwise operators:

var myEnum = {
  left: 1,
  right: 2,
  top: 4,
  bottom: 8
}

var myConfig = myEnum.left | myEnum.right;

if (myConfig & myEnum.right) {
  // right flag is set
}

More info:

查看更多
smile是对你的礼貌
3楼-- · 2019-03-08 13:41

Yes, bitwise arithmetic works in Javascript. You have to be careful with it because Javascript only has the Number data type, which is implemented as a floating-point type. But, values are converted to signed 32-bit values for bitwise operations. So as long as you don't try to use more than 31 bits, you'll be fine.

查看更多
对你真心纯属浪费
4楼-- · 2019-03-08 13:57

I've tried to create an example that demonstrates a common use case where one may want to use bit mask enums to control logging verbosity. It demonstrates the us of JavaScript bit-wise operations: See it on 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");
}
查看更多
狗以群分
5楼-- · 2019-03-08 13:58

In javascript you should be able to combine them as:

var left_right = MyEnum.Left | MyEnum.Right;

Then testing would be exactly as it is in your example of

if ( (left_right & MyEnum.Left) == MyEnum.Left) {...}
查看更多
登录 后发表回答