以下内容是否会使对象满足枚举在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
}
还是有其他方法可以做到这一点?
当前回答
您可以使用Object.protype.hasOwnProperty()
变量findInEnum,颜色枚举={红色:0,绿色:1,蓝色:2};//稍后findInEnum=函数(enumKey){if(colorEnum.hasOwnProperty(enumKey)){return enumKey+“值:”+colorEnum[nenumKey]}}警报(findInEnum(“蓝色”))
其他回答
一种快速而简单的方法是:
var Colors = function(){
return {
'WHITE':0,
'BLACK':1,
'RED':2,
'GREEN':3
}
}();
console.log(Colors.WHITE) //this prints out "0"
您只需要使用object.freeze(<your_object>)创建一个不可变的对象:
export const ColorEnum = Object.freeze({
// you can only change the property values here
// in the object declaration like in the Java enumaration
RED: 0,
GREEN: 1,
BLUE: 2,
});
ColorEnum.RED = 22 // assigning here will throw an error
ColorEnum.VIOLET = 45 // even adding a new property will throw an error
底线:你不能。
你可以伪造它,但你不会得到类型安全。通常,这是通过创建映射到整数值的字符串值的简单字典来完成的。例如:
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
虽然它可能不适合枚举的每一种有效使用,但它需要很长的路。
截至2014年10月的撰写,这里有一个当代的解决方案。我将解决方案作为节点模块编写,并使用Mocha和Chai以及undercoreJS进行了测试。您可以很容易地忽略这些,如果愿意,只需使用Enum代码。
看到了很多带有过于复杂的库等的帖子。在Javascript中获得枚举支持的解决方案非常简单,真的不需要。代码如下:
文件:enums.js
_ = require('underscore');
var _Enum = function () {
var keys = _.map(arguments, function (value) {
return value;
});
var self = {
keys: keys
};
for (var i = 0; i < arguments.length; i++) {
self[keys[i]] = i;
}
return self;
};
var fileFormatEnum = Object.freeze(_Enum('CSV', 'TSV'));
var encodingEnum = Object.freeze(_Enum('UTF8', 'SHIFT_JIS'));
exports.fileFormatEnum = fileFormatEnum;
exports.encodingEnum = encodingEnum;
还有一个测试来说明它给你带来了什么:
文件:enumsSpec.js
var chai = require("chai"),
assert = chai.assert,
expect = chai.expect,
should = chai.should(),
enums = require('./enums'),
_ = require('underscore');
describe('enums', function () {
describe('fileFormatEnum', function () {
it('should return expected fileFormat enum declarations', function () {
var fileFormatEnum = enums.fileFormatEnum;
should.exist(fileFormatEnum);
assert('{"keys":["CSV","TSV"],"CSV":0,"TSV":1}' === JSON.stringify(fileFormatEnum), 'Unexpected format');
assert('["CSV","TSV"]' === JSON.stringify(fileFormatEnum.keys), 'Unexpected keys format');
});
});
describe('encodingEnum', function () {
it('should return expected encoding enum declarations', function () {
var encodingEnum = enums.encodingEnum;
should.exist(encodingEnum);
assert('{"keys":["UTF8","SHIFT_JIS"],"UTF8":0,"SHIFT_JIS":1}' === JSON.stringify(encodingEnum), 'Unexpected format');
assert('["UTF8","SHIFT_JIS"]' === JSON.stringify(encodingEnum.keys), 'Unexpected keys format');
});
});
});
正如您所看到的,您获得了一个Enum工厂,只需调用Enum.keys即可获得所有键,并且可以将键本身与整数常量匹配。您可以使用不同的值重用工厂,并使用Node的模块化方法导出生成的Enum。
同样,如果您只是一个普通用户,或者在浏览器等中,只需使用代码的工厂部分,如果您不想在代码中使用下划线库,也可能会删除它。
我刚刚发布了一个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;