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

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

// later on

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

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


当前回答

尽管ES2015中只支持静态方法(而不支持静态财产)(请参见§15.2.2.2),但奇怪的是,您可以将以下内容用于Babel和ES2015预设:

class CellState {
    v: string;
    constructor(v: string) {
        this.v = v;
        Object.freeze(this);
    }
    static EMPTY       = new CellState('e');
    static OCCUPIED    = new CellState('o');
    static HIGHLIGHTED = new CellState('h');
    static values      = function(): Array<CellState> {
        const rv = [];
        rv.push(CellState.EMPTY);
        rv.push(CellState.OCCUPIED);
        rv.push(CellState.HIGHLIGHTED);
        return rv;
    }
}
Object.freeze(CellState);

我发现,即使在模块之间(例如,从另一个模块导入CellState枚举),以及在使用Webpack导入模块时,这也能正常工作。

与大多数其他答案相比,此方法的优势在于,您可以将其与静态类型检查器(例如Flow)一起使用,并且您可以在开发时使用静态类型检查断言您的变量、参数等是特定的CellState“enum”,而不是其他枚举(如果您使用了泛型对象或符号,则无法区分)。

使现代化

上面的代码有一个缺点,即它允许创建CellState类型的其他对象(尽管由于CellState被冻结,因此无法将它们分配给CellState的静态字段)。尽管如此,以下更精细的代码提供了以下优点:

不能再创建CellState类型的对象可以保证没有两个枚举实例分配了相同的代码从字符串表示中获取枚举的实用方法返回枚举的所有实例的values函数不必以上述手动(且容易出错)的方式创建返回值。“使用严格”;类状态{构造函数(code,displayName=code){if(Status.INSTANCES.has(代码))抛出新错误(`重复代码值:[${code}]`);if(!Status.canCreateMoreInstances)throw new Error(`尝试调用构造函数(${code}`+`,${displayName})在创建所有静态实例后`);this.code=代码;this.displayName=显示名称;对象.冻结(this);Status.INSTANCES.set(this.code,this);}到字符串(){return `[code:${this.code},displayName:${this.displayName}]`;}静态INSTANCES=新映射();静态canCreateMoreInstances=true;//值:静态ARCHIVED=新状态(“存档”);静态观察=新状态(“观察”);静态调度=新状态(“调度”);静态UNOBERVED=新状态(“未观察”);static UNTRIGGERED=新状态(“未触发”);静态值=函数(){return Array.from(Status.INSTANCES.values());}静态fromCode(代码){if(!Status.INSTANCES.has(代码))抛出新错误(“未知代码:${code}”);其他的return Status.INSTANCES.get(代码);}}Status.canCreateMoreInstances=false;对象冻结(状态);exports.Status=状态;

其他回答

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

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

枚举基本上是一个工厂。

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

你的答案太复杂了

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

创建对象文字:

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

尽管ES2015中只支持静态方法(而不支持静态财产)(请参见§15.2.2.2),但奇怪的是,您可以将以下内容用于Babel和ES2015预设:

class CellState {
    v: string;
    constructor(v: string) {
        this.v = v;
        Object.freeze(this);
    }
    static EMPTY       = new CellState('e');
    static OCCUPIED    = new CellState('o');
    static HIGHLIGHTED = new CellState('h');
    static values      = function(): Array<CellState> {
        const rv = [];
        rv.push(CellState.EMPTY);
        rv.push(CellState.OCCUPIED);
        rv.push(CellState.HIGHLIGHTED);
        return rv;
    }
}
Object.freeze(CellState);

我发现,即使在模块之间(例如,从另一个模块导入CellState枚举),以及在使用Webpack导入模块时,这也能正常工作。

与大多数其他答案相比,此方法的优势在于,您可以将其与静态类型检查器(例如Flow)一起使用,并且您可以在开发时使用静态类型检查断言您的变量、参数等是特定的CellState“enum”,而不是其他枚举(如果您使用了泛型对象或符号,则无法区分)。

使现代化

上面的代码有一个缺点,即它允许创建CellState类型的其他对象(尽管由于CellState被冻结,因此无法将它们分配给CellState的静态字段)。尽管如此,以下更精细的代码提供了以下优点:

不能再创建CellState类型的对象可以保证没有两个枚举实例分配了相同的代码从字符串表示中获取枚举的实用方法返回枚举的所有实例的values函数不必以上述手动(且容易出错)的方式创建返回值。“使用严格”;类状态{构造函数(code,displayName=code){if(Status.INSTANCES.has(代码))抛出新错误(`重复代码值:[${code}]`);if(!Status.canCreateMoreInstances)throw new Error(`尝试调用构造函数(${code}`+`,${displayName})在创建所有静态实例后`);this.code=代码;this.displayName=显示名称;对象.冻结(this);Status.INSTANCES.set(this.code,this);}到字符串(){return `[code:${this.code},displayName:${this.displayName}]`;}静态INSTANCES=新映射();静态canCreateMoreInstances=true;//值:静态ARCHIVED=新状态(“存档”);静态观察=新状态(“观察”);静态调度=新状态(“调度”);静态UNOBERVED=新状态(“未观察”);static UNTRIGGERED=新状态(“未触发”);静态值=函数(){return Array.from(Status.INSTANCES.values());}静态fromCode(代码){if(!Status.INSTANCES.has(代码))抛出新错误(“未知代码:${code}”);其他的return Status.INSTANCES.get(代码);}}Status.canCreateMoreInstances=false;对象冻结(状态);exports.Status=状态;