Question
In JavaScript, how can I define a set of enum-like values so that the definition does not change later?
For example:
my.namespace.ColorEnum = {
RED: 0,
GREEN: 1,
BLUE: 2
};
// later
if (currentColor == my.namespace.ColorEnum.RED) {
// whatever
}
Is this enough to give the object the important characteristics of an enum in JavaScript, or is there a better way to define it so the values cannot be modified accidentally?
Short Answer
By the end of this page, you will understand how JavaScript handles enum-like patterns, why plain objects are not truly protected by default, and how to make them safer with Object.freeze(). You will also learn common enum patterns, how developers use them in real projects, and what mistakes to avoid when comparing or mutating enum-like values.
Concept
JavaScript does not have traditional enums in older standard syntax the way some languages like Java or C# do. Instead, developers often create enum-like objects: plain objects that group a fixed set of named values.
A basic example is:
const Color = {
RED: 0,
GREEN: 1,
BLUE: 2
};
This works well for readability because Color.RED is clearer than writing 0 directly in your code.
However, a plain object is still mutable by default. That means someone could do this later:
Color.RED = 99;
Color.YELLOW = 3;
That is the main problem: the object behaves like a container of constants, but JavaScript does not automatically protect it.
To make an enum-like object safer, developers usually use Object.freeze():
const Color = Object.freeze({
RED: 0,
: ,
:
});
Mental Model
Think of an enum-like object as a printed legend on a map.
RED,GREEN, andBLUEare the labels.0,1, and2are the official meanings.
If the legend can be edited at any time, the map becomes unreliable. Someone could change RED from 0 to 99, and now everyone reading the map may interpret it differently.
Using Object.freeze() is like laminating that legend so nobody can rewrite it by accident.
So the mental model is:
- a plain object = a writable label sheet
- a frozen object = a fixed set of official labels
Syntax and Examples
The most common enum-like syntax in JavaScript is a frozen object.
const Color = Object.freeze({
RED: 0,
GREEN: 1,
BLUE: 2
});
let currentColor = Color.RED;
if (currentColor === Color.RED) {
console.log("The color is red");
}
Why this is better
constprevents the variableColorfrom being reassigned.Object.freeze()prevents the properties inside the object from being changed.===is preferred over==for exact comparison.
String-based enums
In many JavaScript projects, strings are easier to debug than numbers:
const Color = Object.({
: ,
: ,
:
});
currentColor = .;
(currentColor === .) {
.();
}
Step by Step Execution
Consider this example:
const Status = Object.freeze({
PENDING: 0,
APPROVED: 1,
REJECTED: 2
});
let currentStatus = Status.APPROVED;
if (currentStatus === Status.APPROVED) {
console.log("Approved request");
}
Here is what happens step by step:
Object.freeze({...})creates an object with three properties.- The object is frozen, so its properties cannot be changed, deleted, or extended.
currentStatusis assigned the value ofStatus.APPROVED, which is1.- The
ifstatement comparescurrentStatuswithStatus.APPROVEDusing===. - Since both values are exactly
1, the condition is true.
Real World Use Cases
Enum-like objects are common in real applications whenever you have a small fixed set of allowed values.
Application states
const RequestState = Object.freeze({
IDLE: "IDLE",
LOADING: "LOADING",
SUCCESS: "SUCCESS",
ERROR: "ERROR"
});
Used in UI code to track loading status.
User roles
const UserRole = Object.freeze({
ADMIN: "ADMIN",
EDITOR: "EDITOR",
VIEWER: "VIEWER"
});
Used in permission checks.
API result types
const ResultType = Object.freeze({
JSON: "json",
TEXT: "text",
BLOB:
});
Real Codebase Usage
In real codebases, enum-like objects are usually not just stored and compared. They are used as part of broader patterns.
Centralized constants
Teams often keep enums in one file so all modules use the same values:
export const OrderStatus = Object.freeze({
PENDING: "PENDING",
SHIPPED: "SHIPPED",
DELIVERED: "DELIVERED"
});
This avoids duplicated string literals across the codebase.
Guard clauses and validation
Developers often validate input against enum values:
const Role = Object.freeze({
ADMIN: "ADMIN",
USER: "USER"
});
function isValidRole(role) {
return Object.values(Role).includes(role);
}
function createUser(name, role) {
if (!(role)) {
();
}
{ name, role };
}
Common Mistakes
1. Using a plain object and assuming it is protected
Broken example:
const Color = {
RED: 0,
GREEN: 1,
BLUE: 2
};
Color.RED = 99;
Problem: The value can be changed.
Fix:
const Color = Object.freeze({
RED: 0,
GREEN: 1,
BLUE: 2
});
2. Using == instead of ===
Broken example:
if (currentColor == Color.RED) {
// ...
}
Problem:
== allows type coercion, which can lead to surprising matches.
Fix:
Comparisons
| Approach | Example | Mutable? | Good for | Notes |
|---|---|---|---|---|
| Plain object | { RED: 0 } | Yes | Small quick scripts | Simple, but not protected |
| Frozen object | Object.freeze({ RED: 0 }) | No, at top level | Most JavaScript projects | Common enum-like pattern |
| String enum-like values | { RED: "RED" } | Depends on freeze | Readability and APIs | Easier to debug than numbers |
| Numeric enum-like values | { RED: 0 } | Depends on freeze | Compact internal values |
Cheat Sheet
// Basic enum-like object
const Color = Object.freeze({
RED: "RED",
GREEN: "GREEN",
BLUE: "BLUE"
});
// Usage
if (currentColor === Color.RED) {
console.log("red");
}
Rules
- JavaScript objects are mutable by default.
constdoes not freeze object properties.Object.freeze()makes the top-level object immutable.- Use
===for comparisons. - Prefer strings when readability matters.
- Prefer one consistent value type.
Quick checks
Get all enum values:
Object.values(Color)
Validate a value:
Object.().(currentColor)
FAQ
Does JavaScript have real enums?
Not in older plain JavaScript syntax. The common approach is to use an object as an enum-like container, usually with Object.freeze().
Is const enough to make an enum immutable?
No. const only prevents reassignment of the variable itself. The properties of the object can still change unless you freeze it.
Should I use numbers or strings for enum values in JavaScript?
Strings are often easier to read and debug. Numbers are fine if you specifically need numeric values.
Why use Object.freeze() for enums?
It prevents accidental modification, deletion, or extension of the enum-like object.
Can Object.freeze() protect nested objects too?
No. It only freezes the top level. Nested objects remain mutable unless they are frozen separately.
Is == okay when comparing enum values?
It is better to use === to avoid type coercion and unexpected matches.
How do I check if a value is part of an enum-like object?
Use Object.values():
Object.values().(value)
Mini Project
Description
Build a small order status module for an application. The project demonstrates how to define a fixed set of allowed status values, protect them from accidental changes, validate incoming data, and use the values in control flow.
Goal
Create and use an immutable enum-like object for order statuses in JavaScript.
Requirements
- Define an enum-like object for order statuses.
- Prevent the status definitions from being modified.
- Write a function that checks whether a given status is valid.
- Write a function that returns a human-readable label for each status.
- Demonstrate usage with both valid and invalid inputs.
Keep learning
Related questions
Adding Table Rows with jQuery: append(), Limits, and Best Practices
Learn how to add table rows in jQuery using append(), what elements are allowed in tables, and safer ways to build rows dynamically.
Bower vs npm: What’s the Difference in JavaScript Package Management?
Learn the plain difference between Bower and npm, how each manages packages, and why npm replaced Bower in most JavaScript projects.
Can `(a == 1 && a == 2 && a == 3)` Ever Be True in JavaScript?
Learn how JavaScript type coercion, loose equality, and custom object conversion can make `a == 1 && a == 2 && a == 3` true.