以下内容是否会使对象满足枚举在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 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
虽然它可能不适合枚举的每一种有效使用,但它需要很长的路。
其他回答
我认为它很容易使用。https://stackoverflow.com/a/32245370/4365315
var A = {a:11, b:22},
enumA = new TypeHelper(A);
if(enumA.Value === A.b || enumA.Key === "a"){
...
}
var keys = enumA.getAsList();//[object, object]
//set
enumA.setType(22, false);//setType(val, isKey)
enumA.setType("a", true);
enumA.setTypeByIndex(1);
更新:
这是我的助手代码(TypeHelper)。
var助手={isEmpty:函数(obj){回来obj | | obj===null | | obj===未定义| | Array.isArray(obj)&&obj.length===0;},isObject:函数(obj){return(对象类型==“object”);},sortObjectKeys:函数(对象){return Object.keys(对象).sort(函数(a,b){c=a-b;返回c});},containsItem:函数(arr,item){if(arr&&Array.isArray(arr)){return arr.indexOf(项)>-1;}其他{返回arr==项;}},pushArray:函数(arr1,arr2){if(arr1&&arr2&&Array.isArray(arr1)){arr1.push.apply(arr1,Array.isArray(arr2)?arr2:[arr2]);}}};函数TypeHelper(){var_types=参数[0],_defTypeIndex=0,_电流类型,_值,_allKeys=助手.sortObjectKeys(_types);if(arguments.length==2){_defTypeIndex=参数[1];}对象定义属性(this{关键字:{get:函数(){return _currentType;},集合:函数(val){_currentType.setType(val,true);},可枚举:真},值:{get:函数(){返回类型[_currentType];},集合:函数(val){_value.setType(val,false);},可枚举:真}});this.getAsList=函数(键){var列表=[];_allKeys.forEach(函数(键、idx、数组){if(键和类型[key]){if(!Helper.isEmpty(keys)&&Helper.containsItem(keys,key)|| Helper.isEmpty(key)){var json={};json.Key=密钥;json.Value=_types[key];Helper.pushArray(列表,json);}}});返回列表;};this.setType=函数(值,isKey){if(!Helper.isEmpty(value)){Object.keys(_types).forEach(函数(key,idx,array){if(Helper.isObject(值)){if(value&&value.Key==Key){_currentType=键;}}else if(isKey){if(value&&value.toString()==key.toString()){_currentType=键;}}否则如果(value&&value.toString()==_types[key]){_currentType=键;}});}其他{this.setDefaultType();}return isKey_类型[_currentType]:_currentType;};this.setTypeByIndex=函数(索引){对于(变量i=0;i<_allKeys.length;i++){如果(索引==i){_currentType=_allKeys[index];打破}}};this.setDefaultType=函数(){this.setTypeByIndex(_defTypeIndex);};this.setDefaultType();}变量类型A={“-1”:“任意”,“2”:“2L”,“100”:“100L”,“200”:“200L”,“1000”:“1000升”};var enumA=新的TypeHelper(TypeA,4);document.writeln(“Key=”,enumA.Key,”,Value=“,enumA.Value,”<br>“);enumA.setType(“200L”,假);document.writeln(“Key=”,enumA.Key,”,Value=“,enumA.Value,”<br>“);enumA.setDefaultType();document.writeln(“Key=”,enumA.Key,”,Value=“,enumA.Value,”<br>“);enumA.setTypeByIndex(1);document.writeln(“Key=”,enumA.Key,”,Value=“,enumA.Value,”<br>“);document.writeln(“等于=”,(enumA.Value==TypeA[“2”]));
我也在寻找这个问题的答案,并找到了这一页的答案,我认为答案与这里的大多数答案不同:https://www.sohamkamani.com/javascript/enums/
我将把文章的答案部分复制到这里,以防将来链接无效或其他情况:
带符号的枚举:符号让我们定义保证不会冲突的值彼此之间。例如:
const Summer1 = Symbol("summer")
const Summer2 = Symbol("summer")
// Even though they have the same apparent value
// Summer1 and Summer2 don't equate
console.log(Summer1 === Summer2)
// false
console.log(Summer1)
我们可以使用符号定义枚举,以确保它们不是复制:
const Summer = Symbol("summer")
const Autumn = Symbol("autumn")
const Winter = Symbol("winter")
const Spring = Symbol("spring")
let season = Spring
switch (season) {
case Summer:
console.log('the season is summer')
break;
case Winter:
console.log('the season is winter')
break;
case Spring:
console.log('the season is spring')
break;
case Autumn:
console.log('the season is autumn')
break;
default:
console.log('season not defined')
}
使用Symbol可以确保我们分配枚举值的唯一方法是使用我们最初定义的常量。
具有类的枚举:
为了使代码更加语义正确,我们可以创建一个类保存一组枚举。例如,我们的季节应该有一种方法来识别它们都属于类似的分类。让我们看看如何使用类和对象创建不同的枚举组:
// Season enums can be grouped as static members of a class
class Season {
// Create new instances of the same class as static attributes
static Summer = new Season("summer")
static Autumn = new Season("autumn")
static Winter = new Season("winter")
static Spring = new Season("spring")
constructor(name) {
this.name = name
}
}
// Now we can access enums using namespaced assignments
// this makes it semantically clear that "Summer" is a "Season"
let season = Season.Summer
// We can verify whether a particular variable is a Season enum
console.log(season instanceof Season)
// true
console.log(Symbol('something') instanceof Season)
//false
// We can explicitly check the type based on each enums class
console.log(season.constructor.name)
// 'Season'
个人注意:我本应该使用此构造函数:(注意:将this.name设置为字符串而不是对象,会丢失以下一些验证。可以选择删除:.description。我还想找到一种方法,不必键入Seasons.summer.name,而只需:Seasons.summer即可使其返回字符串)
constructor(name) {
this.name = Symbol(name).description
}
列出所有可能的枚举值:
如果我们使用上述基于类的方法Season类的键,以获取同一类下的所有枚举值组:
Object.keys(Season).forEach(season => console.log("season:", season))
// season: Summer
// season: Autumn
// season: Winter
// season: Spring
何时在Javascript中使用枚举?
通常,如果有一定数量的固定任何一个变量的值_例如,Node.js的加密标准库有一个受支持的算法列表,可以将其视为枚举组。正确使用Javascript中的enums将产生更好的代码更稳定、更容易阅读和更少出错。
这不是一个很好的答案,但我个人认为这很好
话虽如此,因为值是什么并不重要(您使用了0、1、2),所以我会使用一个有意义的字符串,以防您想要输出当前值。
更新05.11.2020:修改为包含静态字段和方法,以更接近地复制“true”枚举行为。
是否有人尝试过使用包含私有字段和“get”访问器的类执行此操作?我意识到私有类字段目前仍处于实验阶段,但它似乎可以用于创建具有不可变字段/财产的类。浏览器支持也不错。唯一不支持它的“主要”浏览器是Firefox(我相信他们很快就会支持)和IE(谁在乎)。
免责声明:我不是一个开发者。我只是在寻找这个问题的答案,并开始思考我有时如何通过创建带有私有字段和受限属性访问器的类来在C#中创建“增强”枚举。
样本类别
class Sizes {
// Private Fields
static #_SMALL = 0;
static #_MEDIUM = 1;
static #_LARGE = 2;
// Accessors for "get" functions only (no "set" functions)
static get SMALL() { return this.#_SMALL; }
static get MEDIUM() { return this.#_MEDIUM; }
static get LARGE() { return this.#_LARGE; }
}
现在您应该可以直接调用enums。
Sizes.SMALL; // 0
Sizes.MEDIUM; // 1
Sizes.LARGE; // 2
使用私有字段和有限访问器的组合意味着枚举值得到了很好的保护。
Sizes.SMALL = 10 // Sizes.SMALL is still 0
Sizes._SMALL = 10 // Sizes.SMALL is still 0
Sizes.#_SMALL = 10 // Sizes.SMALL is still 0
您可以使用一个简单的函数来反转键和值,当它将数字整数字符串转换为数字时,它也可以处理数组。代码小、简单,可用于此用例和其他用例。
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(音乐样式)