以下内容是否会使对象满足枚举在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
}
还是有其他方法可以做到这一点?
当前回答
截至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。
同样,如果您只是一个普通用户,或者在浏览器等中,只需使用代码的工厂部分,如果您不想在代码中使用下划线库,也可能会删除它。
其他回答
你的答案太复杂了
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
这是我使用的解决方案。
function Enum() {
this._enums = [];
this._lookups = {};
}
Enum.prototype.getEnums = function() {
return _enums;
}
Enum.prototype.forEach = function(callback){
var length = this._enums.length;
for (var i = 0; i < length; ++i){
callback(this._enums[i]);
}
}
Enum.prototype.addEnum = function(e) {
this._enums.push(e);
}
Enum.prototype.getByName = function(name) {
return this[name];
}
Enum.prototype.getByValue = function(field, value) {
var lookup = this._lookups[field];
if(lookup) {
return lookup[value];
} else {
this._lookups[field] = ( lookup = {});
var k = this._enums.length - 1;
for(; k >= 0; --k) {
var m = this._enums[k];
var j = m[field];
lookup[j] = m;
if(j == value) {
return m;
}
}
}
return null;
}
function defineEnum(definition) {
var k;
var e = new Enum();
for(k in definition) {
var j = definition[k];
e[k] = j;
e.addEnum(j)
}
return e;
}
您可以这样定义枚举:
var COLORS = defineEnum({
RED : {
value : 1,
string : 'red'
},
GREEN : {
value : 2,
string : 'green'
},
BLUE : {
value : 3,
string : 'blue'
}
});
以下是访问枚举的方式:
COLORS.BLUE.string
COLORS.BLUE.value
COLORS.getByName('BLUE').string
COLORS.getByValue('value', 1).string
COLORS.forEach(function(e){
// do what you want with e
});
我通常使用最后两种方法从消息对象映射enum。
这种方法的一些优点:
易于声明枚举易于访问您的枚举枚举可以是复杂类型如果经常使用getByValue,Enum类具有一些关联缓存
一些缺点:
由于我保留了对枚举的引用,内存管理有些混乱仍然没有类型安全性
export const ButtonType = Object.freeze({
DEFAULT: 'default',
BIG: 'big',
SMALL: 'small'
})
来源:https://medium.com/@idanlevi2/enum-in-javascript-5f2ff500f149
在大多数现代浏览器中,有一种符号基元数据类型,可用于创建枚举。它将确保枚举的类型安全,因为JavaScript保证每个符号值都是唯一的,即symbol()!=符号()。例如:
const COLOR = Object.freeze({RED: Symbol(), BLUE: Symbol()});
为了简化调试,可以向枚举值添加描述:
const COLOR = Object.freeze({RED: Symbol("RED"), BLUE: Symbol("BLUE")});
Plunker演示
在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
我修改了Andre“Fi”的解决方案:
function Enum() {
var that = this;
for (var i in arguments) {
that[arguments[i]] = i;
}
this.name = function(value) {
for (var key in that) {
if (that[key] == value) {
return key;
}
}
};
this.exist = function(value) {
return (typeof that.name(value) !== "undefined");
};
if (Object.freeze) {
Object.freeze(that);
}
}
测试:
var Color = new Enum('RED', 'GREEN', 'BLUE');
undefined
Color.name(Color.REDs)
undefined
Color.name(Color.RED)
"RED"
Color.exist(Color.REDs)
false
Color.exist(Color.RED)
true