以下内容是否会使对象满足枚举在JavaScript中的所有特性?类似于:

my.namespace.ColorEnum = {
  RED : 0,
  GREEN : 1,
  BLUE : 2
}

// later on

if(currentColor == my.namespace.ColorEnum.RED) {
  // whatever
}

还是有其他方法可以做到这一点?


当前回答

这可能很有用:

const [CATS, DOGS, BIRDS] = ENUM();

实施简单高效:

function * ENUM(count=1) { while(true) yield count++ }

生成器可以产生所需的整数的精确序列,而不知道有多少常数。它还可以支持一个可选参数,该参数指定从哪个(可能是负数)数字开始(默认为1)。

其他回答

更新

我认为我下面的答案不再是用JavaScript编写枚举的最佳方法。有关更多详细信息,请参阅我的博客文章:JavaScript中的枚举。


已经可以提醒名称:

if (currentColor == my.namespace.ColorEnum.RED) {
   // alert name of currentColor (RED: 0)
   var col = my.namespace.ColorEnum;
   for (var name in col) {
     if (col[name] == col.RED)
       alert(name);
   }
}

或者,您可以创建值对象,这样您就可以吃蛋糕了:

var SIZE = {
  SMALL : {value: 0, name: "Small", code: "S"}, 
  MEDIUM: {value: 1, name: "Medium", code: "M"}, 
  LARGE : {value: 2, name: "Large", code: "L"}
};

var currentSize = SIZE.MEDIUM;
if (currentSize == SIZE.MEDIUM) {
  // this alerts: "1: Medium"
  alert(currentSize.value + ": " + currentSize.name);
}

在JavaScript中,因为它是一种动态语言,所以以后甚至可以向集合中添加枚举值:

// Add EXTRALARGE size
SIZE.EXTRALARGE = {value: 3, name: "Extra Large", code: "XL"};

记住,枚举的字段(本例中的值、名称和代码)不需要用于身份检查,只是为了方便。此外,大小属性本身的名称不需要硬编码,也可以动态设置。因此,假设您只知道新枚举值的名称,您仍然可以毫无问题地添加它:

// Add 'Extra Large' size, only knowing it's name
var name = "Extra Large";
SIZE[name] = {value: -1, name: name, code: "?"};

当然,这意味着无法再进行某些假设(例如,该值表示大小的正确顺序)。

记住,在JavaScript中,对象就像一个映射或哈希表。一组名称值对。你可以在事先不了解它们的情况下循环浏览它们或以其他方式操纵它们。

实例

for (var sz in SIZE) {
  // sz will be the names of the objects in SIZE, so
  // 'SMALL', 'MEDIUM', 'LARGE', 'EXTRALARGE'
  var size = SIZE[sz]; // Get the object mapped to the name in sz
  for (var prop in size) {
    // Get all the properties of the size object, iterates over
    // 'value', 'name' and 'code'. You can inspect everything this way.        
  }
} 

顺便说一句,如果你对名称空间感兴趣,你可能想看看我为JavaScript提供的简单但强大的名称空间和依赖关系管理的解决方案:Packages JS

class Enum {
  constructor (...vals) {
    vals.forEach( val => {
      const CONSTANT = Symbol(val);
      Object.defineProperty(this, val.toUpperCase(), {
        get () {
          return CONSTANT;
        },
        set (val) {
          const enum_val = "CONSTANT";
          // generate TypeError associated with attempting to change the value of a constant
          enum_val = val;
        }
      });
    });
  }
}

用法示例:

const COLORS = new Enum("red", "blue", "green");

最简单的解决方案:

创造

var Status = Object.freeze({
    "Connecting":0,
    "Ready":1,
    "Loading":2,
    "Processing": 3
});

获取价值

console.log(Status.Ready) // 1

获取密钥

console.log(Object.keys(Status)[Status.Ready]) // Ready

您可以使用一个简单的函数来反转键和值,当它将数字整数字符串转换为数字时,它也可以处理数组。代码小、简单,可用于此用例和其他用例。

var objInvert=函数(obj){var反转={}for(对象中的变量i){如果(i.match(/^\d+$/))i=parseInt(i,10)反转[obj[i]]=i}返回反转}var musicStyles=对象冻结(objInvert(['ROCK','SURF','METAL',“BOSSA-NOVA”、“op”、“die”]))console.log(音乐样式)

我编写了enumeranjs一个非常小的库来解决这个问题,它确保了类型安全,允许枚举常量从原型继承,保证枚举常量和枚举类型是不可变的+许多小特性。它允许重构大量代码,并在枚举定义中移动一些逻辑。下面是一个示例:

var CloseEventCodes = new Enumeration("closeEventCodes", {
  CLOSE_NORMAL:          { _id: 1000, info: "Connection closed normally" },
  CLOSE_GOING_AWAY:      { _id: 1001, info: "Connection closed going away" },
  CLOSE_PROTOCOL_ERROR:  { _id: 1002, info: "Connection closed due to protocol error"  },
  CLOSE_UNSUPPORTED:     { _id: 1003, info: "Connection closed due to unsupported operation" },
  CLOSE_NO_STATUS:       { _id: 1005, info: "Connection closed with no status" },
  CLOSE_ABNORMAL:        { _id: 1006, info: "Connection closed abnormally" },
  CLOSE_TOO_LARGE:       { _id: 1009, info: "Connection closed due to too large packet" }
},{ talk: function(){
    console.log(this.info); 
  }
});


CloseEventCodes.CLOSE_TOO_LARGE.talk(); //prints "Connection closed due to too large packet"
CloseEventCodes.CLOSE_TOO_LARGE instanceof CloseEventCodes //evaluates to true

枚举基本上是一个工厂。

此处提供完整记录的指南。希望这有帮助。