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

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

// later on

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

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


当前回答

如果您使用的是Backbone,则可以使用Backbone.Collection免费获得完整的枚举功能(按id、名称和自定义成员查找)。

// enum instance members, optional
var Color = Backbone.Model.extend({
    print : function() {
        console.log("I am " + this.get("name"))
    }
});

// enum creation
var Colors = new Backbone.Collection([
    { id : 1, name : "Red", rgb : 0xFF0000},
    { id : 2, name : "Green" , rgb : 0x00FF00},
    { id : 3, name : "Blue" , rgb : 0x0000FF}
], {
    model : Color
});

// Expose members through public fields.
Colors.each(function(color) {
    Colors[color.get("name")] = color;
});

// using
Colors.Red.print()

其他回答

这是我使用的解决方案。

function Enum() {
    this._enums = [];
    this._lookups = {};
}

Enum.prototype.getEnums = function() {
    return _enums;
}

Enum.prototype.forEach = function(callback){
    var length = this._enums.length;
    for (var i = 0; i < length; ++i){
        callback(this._enums[i]);
    }
}

Enum.prototype.addEnum = function(e) {
    this._enums.push(e);
}

Enum.prototype.getByName = function(name) {
    return this[name];
}

Enum.prototype.getByValue = function(field, value) {
    var lookup = this._lookups[field];
    if(lookup) {
        return lookup[value];
    } else {
        this._lookups[field] = ( lookup = {});
        var k = this._enums.length - 1;
        for(; k >= 0; --k) {
            var m = this._enums[k];
            var j = m[field];
            lookup[j] = m;
            if(j == value) {
                return m;
            }
        }
    }
    return null;
}

function defineEnum(definition) {
    var k;
    var e = new Enum();
    for(k in definition) {
        var j = definition[k];
        e[k] = j;
        e.addEnum(j)
    }
    return e;
}

您可以这样定义枚举:

var COLORS = defineEnum({
    RED : {
        value : 1,
        string : 'red'
    },
    GREEN : {
        value : 2,
        string : 'green'
    },
    BLUE : {
        value : 3,
        string : 'blue'
    }
});

以下是访问枚举的方式:

COLORS.BLUE.string
COLORS.BLUE.value
COLORS.getByName('BLUE').string
COLORS.getByValue('value', 1).string

COLORS.forEach(function(e){
    // do what you want with e
});

我通常使用最后两种方法从消息对象映射enum。

这种方法的一些优点:

易于声明枚举易于访问您的枚举枚举可以是复杂类型如果经常使用getByValue,Enum类具有一些关联缓存

一些缺点:

由于我保留了对枚举的引用,内存管理有些混乱仍然没有类型安全性

如果您使用的是Backbone,则可以使用Backbone.Collection免费获得完整的枚举功能(按id、名称和自定义成员查找)。

// enum instance members, optional
var Color = Backbone.Model.extend({
    print : function() {
        console.log("I am " + this.get("name"))
    }
});

// enum creation
var Colors = new Backbone.Collection([
    { id : 1, name : "Red", rgb : 0xFF0000},
    { id : 2, name : "Green" , rgb : 0x00FF00},
    { id : 3, name : "Blue" , rgb : 0x0000FF}
], {
    model : Color
});

// Expose members through public fields.
Colors.each(function(color) {
    Colors[color.get("name")] = color;
});

// using
Colors.Red.print()

创建对象文字:

const Modes = {
  DRAGGING: 'drag',
  SCALING:  'scale',
  CLICKED:  'click'
};

这是我知道的一个旧版本,但它通过TypeScript接口实现的方式是:

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["Foo"] = 0] = "Foo";
    MyEnum[MyEnum["FooBar"] = 2] = "FooBar";
    MyEnum[MyEnum["Bar"] = 1] = "Bar";
})(MyEnum|| (MyEnum= {}));

这使您能够查找返回1的MyEnum.Bar和返回“Bar”的MyEnum[1],无论声明的顺序如何。

这个答案是针对特定情况的另一种方法。我需要一组基于属性子值的位掩码常量(属性值是数组或值列表的情况)。它包含几个重叠枚举的等价物。

我创建了一个类来存储和生成位掩码值。然后,我可以用这种方式使用伪常量位掩码值来测试,例如,如果RGB值中存在绿色:

if (value & Ez.G) {...}

在我的代码中,我只创建了这个类的一个实例。在不实例化类的至少一个实例的情况下,似乎没有一种干净的方法可以做到这一点。以下是类声明和位掩码值生成代码:

class Ez {
constructor() {
    let rgba = ["R", "G", "B", "A"];
    let rgbm = rgba.slice();
    rgbm.push("M");              // for feColorMatrix values attribute
    this.createValues(rgba);
    this.createValues(["H", "S", "L"]);
    this.createValues([rgba, rgbm]);
    this.createValues([attX, attY, attW, attH]);
}
createValues(a) {                // a for array
    let i, j;
    if (isA(a[0])) {             // max 2 dimensions
        let k = 1;
        for (i of a[0]) {
            for (j of a[1]) {
                this[i + j] = k;
                k *= 2;
            }
        }
    }
    else {                       // 1D array is simple loop
        for (i = 0, j = 1; i < a.length; i++, j *= 2)
            this[a[i]] = j;
   }
}

2D数组用于SVG feColorMatrix值属性,该属性是RGBA和RGBAM的4x5矩阵,其中M是乘数。得到的Ez财产为Ez.RR、Ez.RG等。