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

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

// later on

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

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


当前回答

您只需要使用object.freeze(<your_object>)创建一个不可变的对象:

export const ColorEnum = Object.freeze({
    // you can only change the property values here
    // in the object declaration like in the Java enumaration
    RED: 0,
    GREEN: 1,
    BLUE: 2,
});

ColorEnum.RED = 22    // assigning here will throw an error
ColorEnum.VIOLET = 45 // even adding a new property will throw an error

其他回答

截至2014年10月的撰写,这里有一个当代的解决方案。我将解决方案作为节点模块编写,并使用Mocha和Chai以及undercoreJS进行了测试。您可以很容易地忽略这些,如果愿意,只需使用Enum代码。

看到了很多带有过于复杂的库等的帖子。在Javascript中获得枚举支持的解决方案非常简单,真的不需要。代码如下:

文件:enums.js

_ = require('underscore');

var _Enum = function () {

   var keys = _.map(arguments, function (value) {
      return value;
   });
   var self = {
      keys: keys
   };
   for (var i = 0; i < arguments.length; i++) {
      self[keys[i]] = i;
   }
   return self;
};

var fileFormatEnum = Object.freeze(_Enum('CSV', 'TSV'));
var encodingEnum = Object.freeze(_Enum('UTF8', 'SHIFT_JIS'));

exports.fileFormatEnum = fileFormatEnum;
exports.encodingEnum = encodingEnum;

还有一个测试来说明它给你带来了什么:

文件:enumsSpec.js

var chai = require("chai"),
    assert = chai.assert,
    expect = chai.expect,
    should = chai.should(),
    enums = require('./enums'),
    _ = require('underscore');


describe('enums', function () {

    describe('fileFormatEnum', function () {
        it('should return expected fileFormat enum declarations', function () {
            var fileFormatEnum = enums.fileFormatEnum;
            should.exist(fileFormatEnum);
            assert('{"keys":["CSV","TSV"],"CSV":0,"TSV":1}' === JSON.stringify(fileFormatEnum), 'Unexpected format');
            assert('["CSV","TSV"]' === JSON.stringify(fileFormatEnum.keys), 'Unexpected keys format');
        });
    });

    describe('encodingEnum', function () {
        it('should return expected encoding enum declarations', function () {
            var encodingEnum = enums.encodingEnum;
            should.exist(encodingEnum);
            assert('{"keys":["UTF8","SHIFT_JIS"],"UTF8":0,"SHIFT_JIS":1}' === JSON.stringify(encodingEnum), 'Unexpected format');
            assert('["UTF8","SHIFT_JIS"]' === JSON.stringify(encodingEnum.keys), 'Unexpected keys format');
        });
    });

});

正如您所看到的,您获得了一个Enum工厂,只需调用Enum.keys即可获得所有键,并且可以将键本身与整数常量匹配。您可以使用不同的值重用工厂,并使用Node的模块化方法导出生成的Enum。

同样,如果您只是一个普通用户,或者在浏览器等中,只需使用代码的工厂部分,如果您不想在代码中使用下划线库,也可能会删除它。

IE8不支持冻结()方法。资料来源:http://kangax.github.io/compat-table/es5/,单击顶部的“显示过时的浏览器?”,然后检查IE8并冻结行列交叉点。

在我目前的游戏项目中,我使用了以下内容,因为很少有客户仍然使用IE8:

var CONST_WILD_TYPES = {
    REGULAR: 'REGULAR',
    EXPANDING: 'EXPANDING',
    STICKY: 'STICKY',
    SHIFTING: 'SHIFTING'
};

我们还可以做到:

var CONST_WILD_TYPES = {
    REGULAR: 'RE',
    EXPANDING: 'EX',
    STICKY: 'ST',
    SHIFTING: 'SH'
};

或者甚至是这样:

var CONST_WILD_TYPES = {
    REGULAR: '1',
    EXPANDING: '2',
    STICKY: '3',
    SHIFTING: '4'
};

最后一个,对于字符串来说似乎是最有效的,如果您让服务器和客户端交换这些数据,它会减少您的总带宽。当然,现在您有责任确保数据中没有冲突(RE、EX等必须唯一,1、2等也必须唯一)。请注意,为了向后兼容,您需要永远保持这些。

分配:

var wildType = CONST_WILD_TYPES.REGULAR;

对比:

if (wildType === CONST_WILD_TYPES.REGULAR) {
    // do something here
}

我也在寻找这个问题的答案,并找到了这一页的答案,我认为答案与这里的大多数答案不同:https://www.sohamkamani.com/javascript/enums/

我将把文章的答案部分复制到这里,以防将来链接无效或其他情况:

带符号的枚举:符号让我们定义保证不会冲突的值彼此之间。例如:

const Summer1 = Symbol("summer")
const Summer2 = Symbol("summer")

// Even though they have the same apparent value
// Summer1 and Summer2 don't equate
console.log(Summer1 === Summer2)
// false

console.log(Summer1)

我们可以使用符号定义枚举,以确保它们不是复制:

const Summer = Symbol("summer")
const Autumn = Symbol("autumn")
const Winter = Symbol("winter")
const Spring = Symbol("spring")

let season = Spring

switch (season) {
    case Summer:
    console.log('the season is summer')
    break;
    case Winter:
    console.log('the season is winter')
    break;
    case Spring:
    console.log('the season is spring')
    break;
    case Autumn:
    console.log('the season is autumn')
    break;
    default:
    console.log('season not defined')
}

使用Symbol可以确保我们分配枚举值的唯一方法是使用我们最初定义的常量。

具有类的枚举:

为了使代码更加语义正确,我们可以创建一个类保存一组枚举。例如,我们的季节应该有一种方法来识别它们都属于类似的分类。让我们看看如何使用类和对象创建不同的枚举组:

// Season enums can be grouped as static members of a class
class Season {
  // Create new instances of the same class as static attributes
  static Summer = new Season("summer")
  static Autumn = new Season("autumn")
  static Winter = new Season("winter")
  static Spring = new Season("spring")

  constructor(name) {
    this.name = name
  }
}

// Now we can access enums using namespaced assignments
// this makes it semantically clear that "Summer" is a "Season"
let season = Season.Summer

// We can verify whether a particular variable is a Season enum
console.log(season instanceof Season)
// true
console.log(Symbol('something') instanceof Season)
//false

// We can explicitly check the type based on each enums class
console.log(season.constructor.name)
// 'Season'

个人注意:我本应该使用此构造函数:(注意:将this.name设置为字符串而不是对象,会丢失以下一些验证。可以选择删除:.description。我还想找到一种方法,不必键入Seasons.summer.name,而只需:Seasons.summer即可使其返回字符串)

  constructor(name) {
    this.name = Symbol(name).description
  }

列出所有可能的枚举值:

如果我们使用上述基于类的方法Season类的键,以获取同一类下的所有枚举值组:

Object.keys(Season).forEach(season => console.log("season:", season))
// season: Summer
// season: Autumn
// season: Winter
// season: Spring

何时在Javascript中使用枚举?

通常,如果有一定数量的固定任何一个变量的值_例如,Node.js的加密标准库有一个受支持的算法列表,可以将其视为枚举组。正确使用Javascript中的enums将产生更好的代码更稳定、更容易阅读和更少出错。

在ES7中,您可以依靠静态属性执行优雅的ENUM:

class ColorEnum  {
    static RED = 0 ;
    static GREEN = 1;
    static BLUE = 2;
}

然后

if (currentColor === ColorEnum.GREEN ) {/*-- coding --*/}

(使用类而不是文本对象)的优点是有一个父类Enum,然后所有Enum都将扩展该类。

 class ColorEnum  extends Enum {/*....*/}

你的答案太复杂了

var buildSet = function(array) {
  var set = {};
  for (var i in array) {
    var item = array[i];
    set[item] = item;
  }
  return set;
}

var myEnum = buildSet(['RED','GREEN','BLUE']);
// myEnum.RED == 'RED' ...etc