以下内容是否会使对象满足枚举在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
}
还是有其他方法可以做到这一点?
当前回答
我刚刚发布了一个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;
其他回答
最简单的解决方案:
创造
var Status = Object.freeze({
"Connecting":0,
"Ready":1,
"Loading":2,
"Processing": 3
});
获取价值
console.log(Status.Ready) // 1
获取密钥
console.log(Object.keys(Status)[Status.Ready]) // Ready
我制作了一个Enum类,它可以在O(1)处获取值和名称。它还可以生成包含所有名称和值的对象数组。
function Enum(obj) {
// Names must be unique, Values do not.
// Putting same values for different Names is risky for this implementation
this._reserved = {
_namesObj: {},
_objArr: [],
_namesArr: [],
_valuesArr: [],
_selectOptionsHTML: ""
};
for (k in obj) {
if (obj.hasOwnProperty(k)) {
this[k] = obj[k];
this._reserved._namesObj[obj[k]] = k;
}
}
}
(function () {
this.GetName = function (val) {
if (typeof this._reserved._namesObj[val] === "undefined")
return null;
return this._reserved._namesObj[val];
};
this.GetValue = function (name) {
if (typeof this[name] === "undefined")
return null;
return this[name];
};
this.GetObjArr = function () {
if (this._reserved._objArr.length == 0) {
var arr = [];
for (k in this) {
if (this.hasOwnProperty(k))
if (k != "_reserved")
arr.push({
Name: k,
Value: this[k]
});
}
this._reserved._objArr = arr;
}
return this._reserved._objArr;
};
this.GetNamesArr = function () {
if (this._reserved._namesArr.length == 0) {
var arr = [];
for (k in this) {
if (this.hasOwnProperty(k))
if (k != "_reserved")
arr.push(k);
}
this._reserved._namesArr = arr;
}
return this._reserved._namesArr;
};
this.GetValuesArr = function () {
if (this._reserved._valuesArr.length == 0) {
var arr = [];
for (k in this) {
if (this.hasOwnProperty(k))
if (k != "_reserved")
arr.push(this[k]);
}
this._reserved._valuesArr = arr;
}
return this._reserved._valuesArr;
};
this.GetSelectOptionsHTML = function () {
if (this._reserved._selectOptionsHTML.length == 0) {
var html = "";
for (k in this) {
if (this.hasOwnProperty(k))
if (k != "_reserved")
html += "<option value='" + this[k] + "'>" + k + "</option>";
}
this._reserved._selectOptionsHTML = html;
}
return this._reserved._selectOptionsHTML;
};
}).call(Enum.prototype);
您可以这样初始化:
var enum1 = new Enum({
item1: 0,
item2: 1,
item3: 2
});
要获取值(如C#中的枚举):
var val2 = enum1.item2;
要获取某个值的名称(将相同的值用于不同的名称时可能会不明确):
var name1 = enum1.GetName(0); // "item1"
要获取对象中每个名称和值的数组,请执行以下操作:
var arr = enum1.GetObjArr();
将生成:
[{ Name: "item1", Value: 0}, { ... }, ... ]
您还可以轻松获得html选择选项:
var html = enum1.GetSelectOptionsHTML();
其中包含:
"<option value='0'>item1</option>..."
这个答案是针对特定情况的另一种方法。我需要一组基于属性子值的位掩码常量(属性值是数组或值列表的情况)。它包含几个重叠枚举的等价物。
我创建了一个类来存储和生成位掩码值。然后,我可以用这种方式使用伪常量位掩码值来测试,例如,如果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等。
在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 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(音乐样式)