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

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

// later on

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

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


当前回答

底线:你不能。

你可以伪造它,但你不会得到类型安全。通常,这是通过创建映射到整数值的字符串值的简单字典来完成的。例如:

var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}

Document.Write("Enumerant: " + DaysEnum.tuesday);

这种方法有什么问题?您可能会意外地重新定义枚举,或者意外地具有重复的枚举值。例如:

DaysEnum.monday = 4; // whoops, monday is now thursday, too

编辑

Artur Czajka的Object.freeze呢?这难道不会阻止你将星期一设置为星期四吗油炸四方饼

当然,Object.freeze可以完全解决我投诉的问题。我想提醒大家,当我写上述内容时,Object.freeze并不存在。

现在现在它打开了一些非常有趣的可能性。

编辑2这里有一个非常好的用于创建枚举的库。

http://www.2ality.com/2011/10/enums.html

虽然它可能不适合枚举的每一种有效使用,但它需要很长的路。

其他回答

外星人的解决方案是让事情尽可能简单:

使用enum关键字(在javascript中保留)如果enum关键字只是保留的,但未在javascript中实现,请定义以下内容constenumerate=spec=>spec.split(/\s*,\s*/).reduce((e,n)=>对象.assign(e,{[n]:n}),{})

现在,您可以轻松使用它

const kwords = enumerate("begin,end, procedure,if")
console.log(kwords, kwords.if, kwords.if == "if", kwords.undef)

我认为没有理由使枚举值显式变量。无论如何,脚本都是纯文本的,如果代码的一部分是字符串或有效代码,则没有任何区别。真正重要的是,无论何时使用或定义引号,都不需要处理成吨的引号。

你的答案太复杂了

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

你可以这样做

    var Enum = (function(foo) {

    var EnumItem = function(item){
        if(typeof item == "string"){
            this.name = item;
        } else {
            this.name = item.name;
        }
    }
    EnumItem.prototype = new String("DEFAULT");
    EnumItem.prototype.toString = function(){
        return this.name;
    }
    EnumItem.prototype.equals = function(item){
        if(typeof item == "string"){
            return this.name == item;
        } else {
            return this == item && this.name == item.name;
        }
    }

    function Enum() {
        this.add.apply(this, arguments);
        Object.freeze(this);
    }
    Enum.prototype.add = function() {
        for (var i in arguments) {
            var enumItem = new EnumItem(arguments[i]);
            this[enumItem.name] = enumItem;
        }
    };
    Enum.prototype.toList = function() {
        return Object.keys(this);
    };
    foo.Enum = Enum;
    return Enum;
})(this);
var STATUS = new Enum("CLOSED","PENDING", { name : "CONFIRMED", ackd : true });
var STATE = new Enum("CLOSED","PENDING","CONFIRMED",{ name : "STARTED"},{ name : "PROCESSING"});

如此库中所定义。https://github.com/webmodule/foo/blob/master/foo.js#L217

完整示例https://gist.github.com/lnt/bb13a2fd63cdb8bce85fd62965a20026

var ColorEnum = {
    red: {},
    green: {},
    blue: {}
}

您不需要确保不以这种方式将重复的数字分配给不同的枚举值。一个新对象被实例化并分配给所有枚举值。

es7方式,(迭代器,冻结),用法:

const ThreeWiseMen = new Enum('Melchior', 'Caspar', 'Balthazar')

for (let name of ThreeWiseMen)
    console.log(name)


// with a given key
let key = ThreeWiseMen.Melchior

console.log(key in ThreeWiseMen) // true (string conversion, also true: 'Melchior' in ThreeWiseMen)

for (let entry from key.enum)
     console.log(entry)


// prevent alteration (throws TypeError in strict mode)
ThreeWiseMen.Me = 'Me too!'
ThreeWiseMen.Melchior.name = 'Foo'

代码:

class EnumKey {

    constructor(props) { Object.freeze(Object.assign(this, props)) }

    toString() { return this.name }

}

export class Enum {

    constructor(...keys) {

        for (let [index, key] of keys.entries()) {

            Object.defineProperty(this, key, {

                value: new EnumKey({ name:key, index, enum:this }),
                enumerable: true,

            })

        }

        Object.freeze(this)

    }

    *[Symbol.iterator]() {

        for (let key of Object.keys(this))
            yield this[key]

    }

    toString() { return [...this].join(', ') }

}