Reputation: 3350
How do you efficiently cast an int to enum in javascript?
Say I have this enum
enuTable = // Table enum
{
enuUnknown: 0,
enuPerson: 1,
enuItem: 2,
enuSalary: 3,
enuTax: 4,
enuZip: 5,
enuAddress: 6,
enuLocation: 7,
enuTasks: 8,
};
In part of the code I get a return value from an AJAX call that is a number corresponding to one of the above tables.
I can write a switch transforming the value, however is there a more efficient (briefer) way of casting an int to enum? One reason is, I don't want to constantly have to change the switch, in case I change the enum. I guess I could use an array with the enum names and construct an identifier to index into the enum, however again, I would need to change the array every time the enum is changed. I guess what I am looking for is a transparent method, that doesn't require beforehand knowledge of the enum.
Upvotes: 9
Views: 30061
Reputation: 460
I love Yury Tarabanko's solution, but it took me some time to understand what it does (including reading and understanding about reduce(). I can't comment on you @YuryTarabanko, but how did you come up with this?
The solution I whould come up with, is this one. You can access it the same as Yury's solution (keys[ajaxResponseNumber]). I tested it with jsPerf and this is faster in Firefox, but that's not relevant in this case.
var keys = {};
for (var x in enuTable) {
if (enuTable.hasOwnProperty(x)) { keys[enuTable[x]] = x; }
}
Upvotes: 0
Reputation: 64943
First of all, JavaScript doesn't have enumerations like C# has built-in.
Thus, I believe that if you receive an AJAX numeric-based identifier and you want to code a switch
statement, you don't need to cast to Number
in JavaScript, because your switch will compare your pseudo-enumeration property value:
switch(ajaxNumber) {
case enuTable.enuPerson:
break;
}
If you're looking for obtaining the enumeration value label (for example enuPerson
) the following code should be enough (check out a working sample in jsFiddle):
// We're going to implement a basic enumeration prototype to generalize
// what you're looking for so you may re-use this code anywhere!
function Enum(valueMap) {
// We store the enumeration object
this._valueMap = valueMap;
this._valueToLabelMap = {};
var that = this;
// This will create an inverse map: values to labels
Object.keys(valueMap).forEach(function (label) {
that._valueToLabelMap[valueMap[label]] = label;
});
}
Enum.prototype = {
// Getting the whole label is as simple as accessing
// the inverse map where values are the object properties!
getLabel: function (value) {
if (this._valueToLabelMap.hasOwnProperty(value)) {
return this._valueToLabelMap[value];
} else {
throw Error("Enum instance has no defined '" + value + "' value");
}
}
};
var enuTable = new Enum({
enuUnknown: 0,
enuPerson: 1,
enuItem: 2,
enuSalary: 3,
enuTax: 4,
enuZip: 5,
enuAddress: 6,
enuLocation: 7,
enuTasks: 8,
});
// Now, if we provide a number, the fancy Enum prototype will handle it
// so you're going to get the whole enumeration value label!
var taxLabel = enuTable.getLabel(45);
Upvotes: 2
Reputation: 45121
Like this
var keys = Object.keys(enuTable).sort(function(a, b){
return enuTable[a] - enuTable[b];
}); //sorting is required since the order of keys is not guaranteed.
var getEnum = function(ordinal) {
return keys[ordinal];
}
UPD: Is some ordinal values are absent you can use
var keys = Object.keys(enuTable).reduce(function(acc, key) {
return acc[enuTable[key]] = key, acc;
}, {});
Upvotes: 11
Reputation: 1696
One option would be something like the following:
function toTableName(i) {
for(var p in enuTable) {
if(enuTable.hasOwnProperty(p) && enuTable[p] === i) {
return p;
}
}
throw new Error('that\'s no table...');
}
Upvotes: 2