在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
}
还是有更好的成语?
最简单的解决方案:
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
这是实现TypeScript枚举的几种不同方法。
最简单的方法是仅迭代一个对象,向该对象添加反转的键值对。唯一的缺点是您必须手动设置每个成员的值。
function _enum(list) {
for (var key in list) {
list[list[key] = list[key]] = key;
}
return Object.freeze(list);
}
var Color = _enum({
Red: 0,
Green: 5,
Blue: 2
});
// Color → {0: "Red", 2: "Blue", 5: "Green", "Red": 0, "Green": 5, "Blue": 2}
// Color.Red → 0
// Color.Green → 5
// Color.Blue → 2
// Color[5] → Green
// Color.Blue > Color.Green → false
这是一个lodash mixin,用于使用字符串创建枚举。虽然此版本涉及更多点,但它会自动为您编号。本示例中使用的所有lodash方法都具有常规的JavaScript等效项,因此您可以根据需要轻松地将它们切换出来。
function enum() {
var key, val = -1, list = {};
_.reduce(_.toArray(arguments), function(result, kvp) {
kvp = kvp.split("=");
key = _.trim(kvp[0]);
val = _.parseInt(kvp[1]) || ++val;
result[result[val] = key] = val;
return result;
}, list);
return Object.freeze(list);
}
// Add enum to lodash
_.mixin({ "enum": enum });
var Color = _.enum(
"Red",
"Green",
"Blue = 5",
"Yellow",
"Purple = 20",
"Gray"
);
// Color.Red → 0
// Color.Green → 1
// Color.Blue → 5
// Color.Yellow → 6
// Color.Purple → 20
// Color.Gray → 21
// Color[5] → Blue
var ColorEnum = {
red: {},
green: {},
blue: {}
}
您无需确保不会以这种方式将重复的数字分配给不同的枚举值。实例化一个新对象并将其分配给所有枚举值。
如果您使用的骨干,你可以得到全面的枚举功能免费使用(通过ID,名称,自定义成员找到)Backbone.Collection。
// 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()
我知道这是一个古老的方法,但是此后通过TypeScript接口实现的方法是:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["Foo"] = 0] = "Foo";
MyEnum[MyEnum["FooBar"] = 2] = "FooBar";
MyEnum[MyEnum["Bar"] = 1] = "Bar";
})(MyEnum|| (MyEnum= {}));
这样MyEnum.Bar
一来,MyEnum[1]
无论声明的顺序如何,都可以查找返回1以及返回“ Bar”的这两者。
在ES7中,您可以依靠静态属性进行优雅的ENUM:
class ColorEnum {
static RED = 0 ;
static GREEN = 1;
static BLUE = 2;
}
然后
if (currentColor === ColorEnum.GREEN ) {/*-- coding --*/}
优点(使用类而不是文字对象)是拥有父类,Enum
然后您所有的Enums都将扩展该类。
class ColorEnum extends Enum {/*....*/}
这并不是一个很好的答案,但是我个人认为这很好
话虽这么说,因为值无关紧要(您使用过0、1、2),所以如果您想输出当前值,我将使用有意义的字符串。
在大多数现代浏览器中,都有一种符号原始数据类型可用于创建枚举。这将确保枚举的类型安全,因为JavaScript保证每个符号值都是唯一的,即Symbol() != Symbol()
。例如:
const COLOR = Object.freeze({RED: Symbol(), BLUE: Symbol()});
为了简化调试,可以在枚举值中添加描述:
const COLOR = Object.freeze({RED: Symbol("RED"), BLUE: Symbol("BLUE")});
在GitHub上,您可以找到一个包装器,以简化初始化枚举所需的代码:
const color = new Enum("RED", "BLUE")
color.RED.toString() // Symbol(RED)
color.getName(color.RED) // RED
color.size // 2
color.values() // Symbol(RED), Symbol(BLUE)
color.toString() // RED,BLUE
底线:不能。
您可以伪造它,但不会获得类型安全性。通常,这是通过创建映射到整数值的字符串值的简单字典来完成的。例如:
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呢?这样是否可以防止您将星期一设置为星期四?– Fry Quad
绝对Object.freeze
可以完全解决我抱怨的问题。我想提醒大家,当我写上面的文章时,Object.freeze
实际上并不存在。
现在....现在它提供了一些非常有趣的可能性。
编辑2
这是一个用于创建枚举的很好的库。
http://www.2ality.com/2011/10/enums.html
尽管它可能不适合枚举的所有有效用法,但它的路途很长。
从1.8.5开始,可以密封和冻结对象,因此将以上定义为:
const DaysEnum = Object.freeze({"monday":1, "tuesday":2, "wednesday":3, ...})
要么
const DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}
Object.freeze(DaysEnum)
和瞧!JS枚举。
但是,这不会阻止您为变量分配不需要的值,这通常是枚举的主要目标:
let day = DaysEnum.tuesday
day = 298832342 // goes through without any errors
确保类型安全性(使用枚举或其他方式)的程度更高的一种方法是使用诸如TypeScript或Flow之类的工具。
不需要引号,但为了保持一致性,我保留了它们。
你可以做这样的事情
如该库中所定义。 https://github.com/webmodule/foo/blob/master/foo.js#L217
完整示例 https://gist.github.com/lnt/bb13a2fd63cdb8bce85fd62965a20026