Enums in JavaScript | Why You Should Use?

Enums in JavaScript can provide many benefits. They help mitigate spelling errors in the case of a string while also providing an English name for some values that may be numerical. The values are also considered constants and won’t be mutated during runtime — all this, as well as making the code easier to refactor with a single source of truth for the values. What’s not to like?

Let’s take a look at some examples and how to implement enums.

Defining Our Enums

Although JavaScript doesn’t have a native type for enums, we can always create our own using an object. There are a couple of commonly used conventions when defining an enum — although you don’t have to stick to them.

  • The enum name is Capital Case.
  • Avoid abbreviations unless they’re commonly used.
  • Properties are UPPERCASE.
  • Properties are underscore delimited.

With the above in mind, let’s take a look at the following:

const Time = {
  SECONDS_IN_DAY: 86400,
  DAYS_IN_YEAR: 365
}

We have an enum here for some time values that we may be using frequently in our codebase. Instead of having raw numbers floating around, which we may accidentally add a 0 to, we have a constant defined in our enum that should never be changed.

The benefits of using an enum here would be:

  • Auto-completion within IDE/editor
  • Single source of truth
  • Consistency
  • Error highlighting — We might miss a 0 on the value, but we won’t miss a misspelled constant name
  • Searchable by name

NB: An often overlooked benefit is that giving the value a specific name in an enum will allow us to search for all uses of that value in the code. The number 7 might appear a thousand times, but DAYS_PER_WEEK will occur substantially fewer.

Magic Numbers Are Overrated

Encountering magic numbers in code is never fun. What does this seemingly arbitrary 2 mean?

const TransactionStatus = {
  REJECTED: 1,
  ACCEPTED: 2
}

If this were an enum, then the value could have been given an intention-revealing name.

After giving this value a proper name in an enum, we can immediately see what the value is being used for. Naming something accurately in code is important. It makes everything easier to read, reason about, and understand.

With that being said, having raw numbers in our code is not always so indecipherable. Some numbers are so common that we don’t really need to highlight their intent with a name, as long as the code is self-explanatory. Consider the following:

const dailyPay = hourlyRate * 8

We can see clearly that the number 8 represents the number of hours worked in a day. This value does not necessarily warrant being placed in an enum.

Ensure It Is Frozen

Something to consider when creating an enum is to ensure that the object is frozen. Calling the native Object.freeze(value) will prevent mutation of the constants we define. We don’t want these values to ever be changed during runtime.

// Method #1
const Choices = {
  ROCK: 'rock',
  PAPER: 'paper',
  SCISSORS: 'scissors'
}
Object.freeze(Choices)

// Method #2 Probably preferable
const Choices = Object.freeze({
  ROCK: 'rock',
  PAPER: 'paper',
  SCISSORS: 'scissors'
})

When we call this function, we need to pass in our new enum, and its current state will be frozen and returned. The prototype of the object is also frozen. No properties can be modified, added, or removed now.

Choices.ROCK = 'paper' // Returns 'paper'

console.log(Choices.ROCK) // Logs 'rock'

If we now try to mutate the object, the value we try to assign will be returned, but the state of the object will not have been changed. We can see this when we try to log out the enum property. The ROCK property retains its initial value of rock, as we’d expect.

NB: Freezing only applies to the top-layer properties. Nested objects will still be mutable.

Be Careful of the Values Used

Something that may be worth noting is that on occasion, we might encounter a subtle issue. We should be wary of using JavaScript falsy values as values in our enums. They can cause unnecessary headaches.

const Months = {
  JANUARY: 0
}

const foo = month => {
  if (month == Months.JANUARY) {
    console.log('It is January')
  }
}

foo('') // Logs 'It is January'
foo(0) // Logs 'It is January'
foo(false) // Logs 'It is January'

The problem with the above is that our enum is using 0 as the value for January. This is a falsy value in JavaScript, meaning that the conditional we have will evaluate to true. All falsy values will result in the above logging. This also happens because of the loose comparison of == vs. the strict comparison of ===, which is another topic on its own.

Rather, try to stay clear of assigning falsy values in enums.

Conclusion!

Using the concept of enums in JavaScript has many benefits with few drawbacks. While it may not suit every use case, it certainly hits the majority of them. So why not take advantage of them?

Here are some references to resources that may pique your interest, should you wish to either learn more or begin to implement enums into your own codebase, if you’re not already doing so.

Thank you for reading.

#javascript #react #nodejs #programming

Enums in JavaScript | Why You Should Use?
23.50 GEEK