以下内容是否会使对象满足枚举在JavaScript中的所有特性?类似于:
my.namespace.ColorEnum = {
RED : 0,
GREEN : 1,
BLUE : 2
}
// later on
if(currentColor == my.namespace.ColorEnum.RED) {
// whatever
}
还是有其他方法可以做到这一点?
以下内容是否会使对象满足枚举在JavaScript中的所有特性?类似于:
my.namespace.ColorEnum = {
RED : 0,
GREEN : 1,
BLUE : 2
}
// later on
if(currentColor == my.namespace.ColorEnum.RED) {
// whatever
}
还是有其他方法可以做到这一点?
当前回答
这是我们都想要的:
function Enum(constantsList) {
for (var i in constantsList) {
this[constantsList[i]] = i;
}
}
现在,您可以创建枚举:
var YesNo = new Enum(['NO', 'YES']);
var Color = new Enum(['RED', 'GREEN', 'BLUE']);
通过这样做,可以以通常的方式处理常量(YesNo YES,Color.GREEN),并获得一个连续的int值(NO=0,YES=1;RED=0,GREEN=1,BLUE=2)。
还可以使用Enum.prototype添加方法:
Enum.prototype.values = function() {
return this.allValues;
/* for the above to work, you'd need to do
this.allValues = constantsList at the constructor */
};
编辑-小的改进-现在使用varargs:(不幸的是,它不能在IE:S上正常工作……应该继续使用以前的版本)
function Enum() {
for (var i in arguments) {
this[arguments[i]] = i;
}
}
var YesNo = new Enum('NO', 'YES');
var Color = new Enum('RED', 'GREEN', 'BLUE');
其他回答
你可以尝试使用https://bitbucket.org/snippets/frostbane/aAjxM.
my.namespace.ColorEnum = new Enum(
"RED = 0",
"GREEN",
"BLUE"
)
它应该工作到ie8。
这个答案是针对特定情况的另一种方法。我需要一组基于属性子值的位掩码常量(属性值是数组或值列表的情况)。它包含几个重叠枚举的等价物。
我创建了一个类来存储和生成位掩码值。然后,我可以用这种方式使用伪常量位掩码值来测试,例如,如果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等。
我对任何答案都不满意,所以我制作了《又一个枚举》(YEA!)。
此实施:
使用最新的JS只需要这一类的声明即可轻松创建enum具有按名称(colors.RED)、字符串(colors[“RED”])和索引(colors[0])进行的映射,但只需将字符串作为数组传递将等价于String()和valueOf()函数绑定到每个enum对象(如果不希望这样做,可以简单地删除它-不过JS的开销很小)具有可选的全局命名/存储(按名称字符串)创建后冻结枚举对象,使其无法修改
特别感谢Andre‘Fi的回答给了我们一些启发。
代码:
class Enums {
static create({ name = undefined, items = [] }) {
let newEnum = {};
newEnum.length = items.length;
newEnum.items = items;
for (let itemIndex in items) {
//Map by name.
newEnum[items[itemIndex]] = parseInt(itemIndex, 10);
//Map by index.
newEnum[parseInt(itemIndex, 10)] = items[itemIndex];
}
newEnum.toString = Enums.enumToString.bind(newEnum);
newEnum.valueOf = newEnum.toString;
//Optional naming and global registration.
if (name != undefined) {
newEnum.name = name;
Enums[name] = newEnum;
}
//Prevent modification of the enum object.
Object.freeze(newEnum);
return newEnum;
}
static enumToString() {
return "Enum " +
(this.name != undefined ? this.name + " " : "") +
"[" + this.items.toString() + "]";
}
}
用法:
let colors = Enums.create({
name: "COLORS",
items: [ "RED", "GREEN", "BLUE", "PORPLE" ]
});
//Global access, if named.
Enums.COLORS;
colors.items; //Array(4) [ "RED", "GREEN", "BLUE", "PORPLE" ]
colors.length; //4
colors.RED; //0
colors.GREEN; //1
colors.BLUE; //2
colors.PORPLE; //3
colors[0]; //"RED"
colors[1]; //"GREEN"
colors[2]; //"BLUE"
colors[3]; //"PORPLE"
colors.toString(); //"Enum COLORS [RED,GREEN,BLUE,PORPLE]"
//Enum frozen, makes it a real enum.
colors.RED = 9001;
colors.RED; //0
我刚刚发布了一个NPM包gen_enum,它允许您在Javascript中快速创建enum数据结构:
var genEnum = require('gen_enum');
var AppMode = genEnum('SIGN_UP, LOG_IN, FORGOT_PASSWORD');
var curMode = AppMode.LOG_IN;
console.log(curMode.isLogIn()); // output true
console.log(curMode.isSignUp()); // output false
console.log(curMode.isForgotPassword()); // output false
这个小工具的一个优点是在现代环境中(包括nodejs和IE9+浏览器),返回的Enum对象是不可变的。
有关更多信息,请结账https://github.com/greenlaw110/enumjs
更新
我淘汰了gen_enum包,并将该函数合并到constjs包中,该包提供了更多功能,包括不可变对象、JSON字符串反序列化、字符串常量和位图生成等。签出https://www.npmjs.com/package/constjs了解更多信息
要从gen_enum升级到constjs,只需更改语句
var genEnum = require('gen_enum');
to
var genEnum = require('constjs').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()