Enums in JavaScript are a way to define a set of named values that remain constant throughout the code. They provide a means for developers to establish a collection of named constants that can be employed throughout the codebase to enhance error handling, readability, and sustainability.
Enumerations, commonly referred to as enums, are utilized in JavaScript to represent a defined set of named values. Given that JavaScript does not have built-in support for enums, they are usually simulated using objects or immutable arrays.
The enum can include weekdays such as {"SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY"}, colors like {"BLUE, RED, YELLOW, PINK, GREEN"}, seasons such as {"SUMMER, AUTUMN or FALL, SPRING, WINTER"}, and directions like {"EAST, WEST, NORTH, SOUTH, NORTH EAST, SOUTH EAST, and SOUTH WEST"}.
Does Enum Support JavaScript?
JavaScript does not have a built-in enum data type, unlike other programming languages such as C++ and Java that commonly utilize enum data types. Enum functionality can be achieved in JavaScript by leveraging classes and objects.
Syntax:
const EnumType = {
<enumConstant1> : <value1>,
<enumConstant2> : <value2>,
...
<enumConstantN> : <valueN>
}
An illustration showcasing the utilization of enum types with numerical values in our JavaScript code will be examined.
<!DOCTYPE html>
<html>
<head>
<title>HTML Editor</title>
</head>
<body>
<h3> Output Screen </h3>
<p> Output: </p>
<div id="output">
</div>
<div id="Error" style="color : pink">
</div>
<script>
var content = ''
var error = ''
var opDiv = document.querySelector('#output')
var opErrDiv = document.querySelector('#Error')
// actual JavaScript code
try {
const ourDirection = {
East: 1,
West: 2,
North: 3,
South: 4,
NorthEast: 5,
NorthWest: 6,
SouthEast: 7,
SouthWest: 8,
}
let myDirection = 1
if (myDirection === ourDirection.East) {
content += "Our direction is East" + '<br>'
}
}
catch (err) {
error += err
}
finally {
// display on output console
opDiv.innerHTML = content
opErrDiv.innerHTML = error
}
</script>
</body>
</html>
Output:
This method can be applied in small codebases, although there are situations where it may introduce uncertainty. For instance, a developer might input the command as shown below, with the initial letter in lowercase, only to encounter a failed string comparison resulting in a false outcome.
<!DOCTYPE html>
<html>
<head>
<title>HTML Screen</title>
</head>
<body>
<h3> Output Screen </h3>
<p> Output: </p>
<div id="output">
</div>
<div id="Error" style="color : pink">
</div>
<script>
var content = ''
var error = ''
var opDiv = document.querySelector('#output')
var opErrDiv = document.querySelector('#Error')
// actual JavaScript code
try {
const Direction = {
E: 'East',
W: 'West',
N: 'North',
S: 'South',
NE: 'North-East',
NW: 'North-West',
SE: 'South-East',
SW: 'South-West',
}
let ourDirection = 'North-East'
if (ourDirection === Direction.SE) {
content += "Yes, your direction is North-East" + '<br>'
} else {
content += "No, your direction is not South-East" + '<br>'
}
}
catch (err) {
error += err
}
finally {
// display on output console
opDiv.innerHTML = content
opErrDiv.innerHTML = error
}
</script>
</body>
</html>
Output:
Developers might unintentionally create unrelated enums with only two values of a primitive type, causing conditional operators to mistakenly compare them. Let's explore this scenario through an example.
<!DOCTYPE html>
<html>
<head>
<title>HTML Output</title>
</head>
<body>
<h3> Output Screen </h3>
<p> Output: </p>
<div id="output">
</div>
<div id="opError" style="color : green">
</div>
<script>
var content = ''
var error = ''
var opDiv = document.querySelector('#output')
var opErrDiv = document.querySelector('#opError')
// actual JavaScript code
try {
const Direction = {
East: 10,
West: 20,
North: 30,
South: 40,
NorthEast: 5,
NorthWest: 6,
SouthEast: 7,
SouthWest: 8,
}
const Car = {
Audi: 10,
BMW: 20,
Tata: 30,
Kia: 40
}
if (Direction.South === Car.Kia) {
content += "Our car type is Kia" + '<br>'
}
}
catch (err) {
error += err
}
finally {
// display on output console
opDiv.innerHTML = content
opErrDiv.innerHTML = error
}
</script>
</body>
</html>
Output:
In this instance, two separate enum variations are created, yet they become mixed up while being checked for their values within the if block. An alternative approach is desired. Additionally, it is illogical to utilize integers or numeric values. For example, categories like Directions should be more appropriately depicted as they are not strings, integers, or numeric values.
Enums with Symbol types
Within JavaScript, there exists a concept referred to as Symbol. Symbols are unique and do not clash with one another. Utilizing symbols to define values is a more appropriate approach that reduces the likelihood of errors. The following demonstrates the syntax for using symbols:
Syntax:
const EnumType = {
const EnumType = {
<enumConstant1> : Symbol(<value1>),
<enumConstant2> : Symbol(<value2>),
...
<enumConstantN> : Symbol(<valueN>)
}
Consider a similar scenario where symbols are used and assess whether they intersect or not.
<html>
<head>
<title>HTML Screen</title>
</head>
<body>
<h3> Output Screen </h3>
<p> Output: </p>
<div id="output">
</div>
<div id="opError" style="color : red">
</div>
<script>
var content = ''
var error = ''
var opDiv = document.querySelector('#output')
var opErrDiv = document.querySelector('#opError')
// actual JavaScript code
try {
const ourDays = {
Sunday: Symbol(1),
Monday: Symbol(2),
Tuesday: Symbol(3),
Wednesday: Symbol(4),
Thursday: Symbol(5),
Friday: Symbol(6),
Saturday: Symbol(7),
}
const Car = {
Kia: Symbol(1),
Honda: Symbol(2),
Ferrari: Symbol(3),
Tata: Symbol(4),
Audi: Symbol(5),
}
if (ourDays.Tuesday === Car.Ferrari) {
content += "Our day is Thursday" + '<br>'
} else {
content += "Not checking same data types" + '<br>'
}
}
catch (err) {
error += err
}
finally {
// display on output console
opDiv.innerHTML = content
opErrDiv.innerHTML = error
}
</script>
</body>
</html>
Output:
Creating Immutable Enum types
There have been limited instances of enumeration implementations discovered to date. Yet, there are certain challenges associated with this. It is possible to modify the value of an enum type in the end approach simply by assigning it a new value. To restrict enum updates, one can make it immutable by passing the object through the Object.freeze method. Let's exemplify this.
Syntax:
const EnumType = Object.freeze({
<enumConstant1> : Symbol(<value1>),
<enumConstant2> : Symbol(<value2>),
...
<enumConstantN> : Symbol(<valueN>)
})
Example
<!DOCTYPE html>
<html>
<head>
<title>HTML Console</title>
</head>
<body>
<h3> Output Console </h3>
<p> Output: </p>
<div id="output">
</div>
<div id="opError" style="color : red">
</div>
<script>
var content = ''
var error = ''
var opDiv = document.querySelector('#output')
var opErrDiv = document.querySelector('#opError')
// actual JavaScript code
try {
const ourDays = {
Monday: Symbol(1),
Tuesday: Symbol(2),
Wednesday: Symbol(3),
Thursday: Symbol(4),
Friday: Symbol(5),
Saturday: Symbol(6),
}
content += "Value of Monday: " +
JSON.stringify(ourDays.Monday.toString()) + '<br>'
ourDays.SE = Symbol(1); // updating with a new value
content += "Value of Tuesday: " +
JSON.stringify(ourDays.Tuesday.toString()) + '<br>'
// creating an immutable object type
const Car = Object.freeze({
Audi: Symbol(1),
Tata: Symbol(2),
BMW: Symbol(3),
Kia: Symbol(4),
})
content += "Value of Car: " +
JSON.stringify(Car.Audi.toString()) + '<br>'
Car.Audi = Symbol(1); // updating will not affect the old value
content += "Value of Car: " + JSON.stringify(Car.Audi.toString()) + '<br>'
}
catch (err) {
error += err
}
finally {
// display on output console
opDiv.innerHTML = content
opErrDiv.innerHTML = error
}
</script>
</body>
</html>
Output:
In summary
In order to enhance the readability of our code, we can utilize a structured set of fixed values generated using the enum data types in JavaScript. Unlike some other programming languages, JavaScript does not offer built-in support for enums. There are various techniques available for implementing enums in JavaScript programs. While basic enums can be established through objects with numeric or text values, this method may not be ideal in scenarios where enum clashes can occur. Employing symbols to avert conflicts is a viable solution. Leveraging classes as enum types stands out as the most effective approach to ensure our enums remain unchangeable, thus avoiding unnecessary alterations.