๐ฆ๐ฒ๐น๐ณ-๐๐ฒ๐๐ฐ๐ฟ๐ถ๐ฝ๐๐ถ๐๐ฒ ๐๐
๐๐ฒ๐ป๐๐ถ๐ฏ๐น๐ฒ ๐ฉ๐ฎ๐ฟ๐ถ๐ฎ๐ฏ๐น๐ฒ ๐ก๐ฎ๐บ๐ฒ๐
Let's cut straight to the problem: file size. Every other answer listed here bloats your minified code to the extreme. I present to you that for the best possible reduction in code size by minification, performance, readability of code, large scale project management, and syntax hinting in many code editors, this is the correct way to do enumerations: underscore-notation variables.

As demonstrated in the chart above and example below, here are five easy steps to get started:
- Determine a name for the enumeration group. Think of a noun that can describe the purpose of the enumeration or at least the entries in the enumeration. For example, a group of enumerations representing colors choosable by the user might be better named COLORCHOICES than COLORS.
- Decide whether enumerations in the group are mutually-exclusive or independent. If mutually-exclusive, start each enumerated variable name with
ENUM_
. If independent or side-by-side, use INDEX_
.
- For each entry, create a new local variable whose name starts with
ENUM_
or INDEX_
, then the name of the group, then an underscore, then a unique friendly name for the property
- Add a
ENUMLENGTH_
, ENUMLEN_
, INDEXLENGTH_
, or INDEXLEN_
(whether LEN_
or LENGTH_
is personal preference) enumerated variable at the very end. You should use this variable wherever possible in your code to ensure that adding an extra entry to the enumeration and incrementing this value won't break your code.
- Give each successive enumerated variable a value one more than the last, starting at 0. There are comments on this page that say
0
should not be used as an enumerated value because 0 == null
, 0 == false
, 0 == ""
, and other JS craziness. I submit to you that, to avoid this problem and boost performance at the same time, always use ===
and never let ==
appear in your code except with typeof
(e.x. typeof X == "string"
). In all my years of using ===
, I have never once had a problem with using 0 as an enumeration value. If you are still squeamish, then 1
could be used as the starting value in ENUM_
enumerations (but not in INDEX_
enumerations) without performance penalty in many cases.
const ENUM_COLORENUM_RED = 0;
const ENUM_COLORENUM_GREEN = 1;
const ENUM_COLORENUM_BLUE = 2;
const ENUMLEN_COLORENUM = 3;
if(currentColor === ENUM_COLORENUM_RED) {
}
Here is how I remember when to use INDEX_
and when to use ENUM_
:
arr[INDEX_] = ENUM_;
However, ENUM_
can, in certain circumstances, be appropriate as an index such as when counting the occurrences of each item.
const ENUM_PET_CAT = 0,
ENUM_PET_DOG = 1,
ENUM_PET_RAT = 2,
ENUMLEN_PET = 3;
var favoritePets = [ENUM_PET_CAT, ENUM_PET_DOG, ENUM_PET_RAT,
ENUM_PET_DOG, ENUM_PET_DOG, ENUM_PET_CAT,
ENUM_PET_RAT, ENUM_PET_CAT, ENUM_PET_DOG];
var petsFrequency = [];
for (var i=0; i<ENUMLEN_PET; i=i+1|0)
petsFrequency[i] = 0;
for (var i=0, len=favoritePets.length|0, petId=0; i<len; i=i+1|0)
petsFrequency[petId = favoritePets[i]|0] = (petsFrequency[petId]|0) + 1|0;
console.log({
"cat": petsFrequency[ENUM_PET_CAT],
"dog": petsFrequency[ENUM_PET_DOG],
"rat": petsFrequency[ENUM_PET_RAT]
});
Observe that, in the code above, it's really easy to add in a new kind of pet: you would just have to append a new entry after ENUM_PET_RAT
and update ENUMLEN_PET
accordingly. It might be more difficult and buggy to add a new entry in other systems of enumeration.
๐๐
๐๐ฒ๐ป๐ฑ ๐จ๐ฝ๐ฝ๐ฒ๐ฟ๐ฐ๐ฎ๐๐ฒ ๐ฉ๐ฎ๐ฟ๐ถ๐ฎ๐ฏ๐น๐ฒ๐ ๐ช๐ถ๐๐ต ๐๐ฑ๐ฑ๐ถ๐๐ถ๐ผ๐ป
Additionally, this syntax of enumerations allows for clear and concise class extending as seen below. To extend a class, add an incrementing number to the LEN_
entry of the parent class. Then, finish out the subclass with its own LEN_
entry so that the subclass may be extended further in the future.

(function(window){
"use strict";
var parseInt = window.parseInt;
const INDEX_PIXELCOLOR_TYPE = 0,
INDEXLEN_PIXELCOLOR = 1,
INDEX_SOLIDCOLOR_R = INDEXLEN_PIXELCOLOR+0,
INDEX_SOLIDCOLOR_G = INDEXLEN_PIXELCOLOR+1,
INDEX_SOLIDCOLOR_B = INDEXLEN_PIXELCOLOR+2,
INDEXLEN_SOLIDCOLOR = INDEXLEN_PIXELCOLOR+3,
INDEX_ALPHACOLOR_R = INDEXLEN_PIXELCOLOR+0,
INDEX_ALPHACOLOR_G = INDEXLEN_PIXELCOLOR+1,
INDEX_ALPHACOLOR_B = INDEXLEN_PIXELCOLOR+2,
INDEX_ALPHACOLOR_A = INDEXLEN_PIXELCOLOR+3,
INDEXLEN_ALPHACOLOR = INDEXLEN_PIXELCOLOR+4,
ENUM_PIXELTYPE_SOLID = 0,
ENUM_PIXELTYPE_ALPHA = 1,
ENUM_PIXELTYPE_UNKNOWN = 2,
ENUMLEN_PIXELTYPE = 2;
function parseHexColor(inputString) {
var rawstr = inputString.trim().substring(1);
var result = [];
if (rawstr.length === 8) {
result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_ALPHA;
result[INDEX_ALPHACOLOR_R] = parseInt(rawstr.substring(0,2), 16);
result[INDEX_ALPHACOLOR_G] = parseInt(rawstr.substring(2,4), 16);
result[INDEX_ALPHACOLOR_B] = parseInt(rawstr.substring(4,6), 16);
result[INDEX_ALPHACOLOR_A] = parseInt(rawstr.substring(4,6), 16);
} else if (rawstr.length === 4) {
result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_ALPHA;
result[INDEX_ALPHACOLOR_R] = parseInt(rawstr[0], 16) * 0x11;
result[INDEX_ALPHACOLOR_G] = parseInt(rawstr[1], 16) * 0x11;
result[INDEX_ALPHACOLOR_B] = parseInt(rawstr[2], 16) * 0x11;
result[INDEX_ALPHACOLOR_A] = parseInt(rawstr[3], 16) * 0x11;
} else if (rawstr.length === 6) {
result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_SOLID;
result[INDEX_SOLIDCOLOR_R] = parseInt(rawstr.substring(0,2), 16);
result[INDEX_SOLIDCOLOR_G] = parseInt(rawstr.substring(2,4), 16);
result[INDEX_SOLIDCOLOR_B] = parseInt(rawstr.substring(4,6), 16);
} else if (rawstr.length === 3) {
result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_SOLID;
result[INDEX_SOLIDCOLOR_R] = parseInt(rawstr[0], 16) * 0x11;
result[INDEX_SOLIDCOLOR_G] = parseInt(rawstr[1], 16) * 0x11;
result[INDEX_SOLIDCOLOR_B] = parseInt(rawstr[2], 16) * 0x11;
} else {
result[INDEX_PIXELCOLOR_TYPE] = ENUM_PIXELTYPE_UNKNOWN;
}
return result;
}
console.log(parseHexColor("#0f0")[INDEX_SOLIDCOLOR_R]);
console.log(parseHexColor("#f0f7")[INDEX_ALPHACOLOR_A]);
console.log(parseHexColor("#40E0D0"));
})(self);
(Length: 2,450 bytes)
Some may say that this is less practical than other solutions: it wastes tons of space, it takes a long time to write, and it is not coated with sugar syntax. Those people would be right if they do not minify their code. However, no reasonable person would leave unminified code in the end product. For this minification, Closure Compiler is the best I have yet to find. Online access can be found here. Closure compiler is able to take all of this enumeration data and inline it, making your Javascript be super duper small and run super duper fast. Thus, Minify with Closure Compiler. Observe.
Closure compiler is able to perform some pretty incredible optimizations via inferences that are way beyond the capacities of any other Javascript minifier. Closure Compiler is able to inline primitive variables set to a fixed value. Closure Compiler is also able to make inferences based upon these inlined values and eliminate unused blocks in if-statements and loops.

'use strict';(function(e){function d(a){a=a.trim().substring(1);var b=[];8===a.length?(b[0]=1,b[1]=c(a.substring(0,2),16),b[2]=c(a.substring(2,4),16),b[3]=c(a.substring(4,6),16),b[4]=c(a.substring(4,6),16)):4===a.length?(b[1]=17*c(a[0],16),b[2]=17*c(a[1],16),b[3]=17*c(a[2],16),b[4]=17*c(a[3],16)):6===a.length?(b[0]=0,b[1]=c(a.substring(0,2),16),b[2]=c(a.substring(2,4),16),b[3]=c(a.substring(4,6),16)):3===a.length?(b[0]=0,b[1]=17*c(a[0],16),b[2]=17*c(a[1],16),b[3]=17*c(a[2],16)):b[0]=2;return b}var c=
e.parseInt;console.log(d("#0f0")[1]);console.log(d("#f0f7")[4]);console.log(d("#40E0D0"))})(self);
(Length: 605 bytes)
Closure Compiler rewards you for coding smarter and organizing your code well because, whereas many minifiers punish organized code with a bigger minified file size, Closure Compiler is able to sift through all your cleanliness and sanity to output an even smaller file size if you use tricks like variable name enumerations. That, in this one mind, is the holy grail of coding: a tool that both assists your code with a smaller minified size and assists your mind by training better programming habits.
๐ฆ๐บ๐ฎ๐น๐น๐ฒ๐ฟ ๐๐ผ๐ฑ๐ฒ ๐ฆ๐ถ๐๐ฒ
Now, let us see how big the equivalent file would be without any of these enumerations.
Source Without Using Enumerations (length: 1,973 bytes (477 bytes shorter than enumerated code!))
Minified Without Using Enumerations (length: 843 bytes (238 bytes longer than enumerated code))

As seen, without enumerations, the source code is shorter at the cost of a larger minified code. I do not know about you; but I know for sure that I do not incorporate source code into the end product. Thus, this form of enumerations is far superior insomuch that it results in smaller minified file sizes.
๐๐ผ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ถ๐๐ฒ ๐ค ๐๐๐ด ๐๐ถ๐
๐ถ๐ป๐ด
Another advantage about this form of enumeration is that it can be used to easily manage large scale projects without sacrificing minified code size. When working on a large project with lots of other people, it might be beneficial to explicitly mark and label the variable names with who created the code so that the original creator of the code can be quickly identified for collaborative bug fixing.
const ENUM_JG_COLORENUM_RED = 0,
ENUM_JG_COLORENUM_GREEN = 1,
ENUM_JG_COLORENUM_BLUE = 2,
ENUMLEN_JG_COLORENUM = 3;
if(currentColor === ENUM_JG_COLORENUM_RED) {
}
const ENUM_PL_ARRAYTYPE_UNSORTED = 0,
ENUM_PL_ARRAYTYPE_ISSORTED = 1,
ENUM_BK_ARRAYTYPE_CHUNKED = 2,
ENUM_JG_ARRAYTYPE_INCOMPLETE = 3,
ENUMLEN_PL_COLORENUM = 4;
if(
randomArray === ENUM_PL_ARRAYTYPE_UNSORTED ||
randomArray === ENUM_BK_ARRAYTYPE_CHUNKED
) {
}
๐ฆ๐๐ฝ๐ฒ๐ฟ๐ถ๐ผ๐ฟ ๐ฃ๐ฒ๐ฟ๐ณ๐ผ๐ฟ๐บ๐ฎ๐ป๐ฐ๐ฒ 
Further, this form of enumeration is also much faster after minification. In normal named properties, the browser has to use hashmaps to look up where the property is on the object. Although JIT compilers intelligently cache this location on the object, there is still tremendous overhead due to special cases such as deleting a lower property from the object.

But, with continuous non-sparse integer-indexed PACKED_ELEMENTS arrays, the browser is able to skip much of that overhead because the index of the value in the internal array is already specified. Yes, according to the ECMAScript standard, all properties are supposed to be treated as strings. Nevertheless, this aspect of the ECMAScript standard is very misleading about performance because all browsers have special optimizations for numeric indexes in arrays.
var ref = {};
ref.count = 10;
ref.value = "foobar";
Compare the code above to the code below.
const INDEX_REFERENCE_COUNT = 0;
const INDEX_REFERENCE_VALUE = 1;
const INDEXLENGTH_REFERENCE = 2;
var ref = [];
ref[INDEX_REFERENCE_COUNT] = 10;
ref[INDEX_REFERENCE_VALUE] = "foobar";
One might object to the code with enumerations seeming to be much longer than the code with ordinary objects, but looks can be deceiving. It is important to remember that source code size is not proportional to output size when using the epic Closure Compiler. Observe.
/// Hashmaps are slow, even with JIT juice
var a={count:10,value:"foobar"};
The minified code without enumerations is above and the minified code with enumerations is below.
var a=[10,"foobar"];
The example above demonstrates that, in addition to having superior performance, the enumerated code also results in a smaller minified file size.
๐๐ฎ๐๐ ๐๐ฒ๐ฏ๐๐ด๐ด๐ถ๐ป๐ด
Furthermore, this one's personal cherry on the top is using this form of enumerations along with the CodeMirror text editor in Javascript mode. CodeMirror's Javascript syntax highlighting mode highlights local variables in the current scope. That way, you know instantly when you type in a variable name correctly because if the variable name was previously declared with the var
keyword, then the variable name turns a special color (cyan by default). Even if you do not use CodeMirror, then at least the browser throws a helpful [variable name] is not defined
exception when executing code with mistyped enumeration names. Also, JavaScript tools such as JSLint and Closure Compiler are very loud about telling you when you mistype in an enumeration variable name. CodeMirror, the browser, and various Javascript tools put together make debugging this form of enumeration very simple and really easy.

const ENUM_COLORENUM_RED = 0,
ENUM_COLORENUM_GREEN = 1,
ENUM_COLORENUM_BLUE = 2,
ENUMLEN_COLORENUM = 3;
var currentColor = ENUM_COLORENUM_GREEN;
if(currentColor === ENUM_COLORENUM_RED) {
}
if(currentColor === ENUM_COLORENUM_DNE) {
}
In the above snippet, you were alerted with an error because ENUM_COLORENUM_DNE
does not exist.
๐๐ผ๐ป๐ฐ๐น๐๐๐ถ๐ผ๐ป
I think its safe to say that this methodology of enumeration is indeed the best way to go not just for minified code size, but also for performance, debugging, and collaboration.
0
as an enumeration number. Unless it's used for something that has not been set. JS treatsfalse || undefined || null || 0 || "" || '' || NaN
all as the same value when compared using==
. - matsko0 == null
returns false - mcontfalse == 0
and+null == 0
(and conversions to numbers happen sometimes when you don't expect it), whilenull == undefined
too, and+undefined
isNaN
(thoughNaN != NaN
). - sanderd17