Which JavaScript Keyword Declares a Constant The const Guide
Discover which javascript keyword is used to declare a constant and how const creates a block scoped binding. Learn practical usage, scope, and common pitfalls for safer JavaScript in 2026.

const is a keyword in JavaScript that declares a block-scoped binding which cannot be reassigned.
What does the const keyword do in JavaScript?
In JavaScript, the const keyword declares a block-scoped binding that cannot be reassigned. This means once you assign a value to a const, you cannot rebind that name to a new value within the same scope. The binding is fixed for its scope, which helps prevent accidental changes and makes intent clear.
Example:
const greeting = 'Hello';
// greeting = 'Hi'; // TypeError: Assignment to constant variable.
const numbers = [1,2,3];
numbers.push(4); // Allowed
// numbers = [0]; // TypeError: Assignment to constant variable.Keep in mind that const does not make the value itself immutable. If the bound value is an object or array, its properties or elements can still be changed. To enforce immutability, you can use Object.freeze or immutable data structures. Also, a const binding must be initialized at declaration; no TDZ until the code reaches the declaration. This is why const helps enforce invariants in your code.
How const compares to let and var
The const keyword creates a binding that cannot be reassigned, which means you cannot later assign a different value to the same binding. In contrast, let creates a mutable binding that can be reassigned within its block. Var, the older declaration, is function-scoped rather than block-scoped and can lead to hoisting quirks. For most modern codebases, favor const by default and use let only when you know the value will change. In practice, this reduces bugs by signaling intent through the code. Also, remember that reassigning an object’s properties is not the same as reassigning the binding; with const, you can still mutate the object, but you cannot replace the object reference itself. This distinction is essential for understanding how to manage state in functions, modules, and components.
Temporal dead zone and initialization rules
A key aspect of const is that it is subject to the temporal dead zone. The binding exists in the scope, but you cannot read it until after the line where it is initialized. Accessing a const variable before its declaration throws a ReferenceError. This behavior helps catch errors early and encourages declaring constants at the top of a scope where possible. Additionally, every const declaration must include an initialization value; leaving it uninitialized is a syntax error. These rules ensure that const is used for values that truly should be fixed in the lifetime of the scope. If you expect to programmatically determine a value later, choose let instead of const to avoid TDZ issues.
Mutating content of const bound objects and arrays
A common source of confusion is how const interacts with objects and arrays. If you declare an array or object with const, you cannot rebind the variable to a new array or object, but you can still change the contents. For example, you can push into an array or modify a property of an object declared with const. This is because the binding remains fixed to the original array or object reference, while the interior can be mutated. To guard against any mutation, you can use Object.freeze, which makes the top-level properties immutable, and deep freeze utilities for nested structures. Use this pattern sparingly, because freezing can complicate code and may have performance considerations in hot paths. In many cases, rethinking data shapes or using functional patterns can reduce mutation altogether.
Best practices and common patterns
- Default to const unless you need mutation. This simple rule improves readability and maintainability.
- Use descriptive names for values declared with const so intent is obvious. Prefer immutable data structures and avoid unnecessary mutation.
- Be mindful of TDZ and initialization order; structure modules so constants are initialized early in a module or function.
- For configuration values or static data that will be used across modules, consider exporting a frozen object to protect against accidental changes.
- In loops, use const for the loop variable if it does not get reassigned within the loop body, otherwise use let. This makes the loop semantics clearer and safer.
Common pitfalls and debugging tips
- Accidentally attempting to reassign a const binding will throw a TypeError at runtime, so code edits should catch this early during development.
- Forgetting about TDZ can lead to ReferenceError; place declarations at the top of modules and use linters to enforce order.
- Assuming that const freezes objects is a common misconception; remember that only the binding is constant, not the contents.
- When dealing with modules, pay attention to circular imports that can lead to partially initialized constants. Use static imports and avoid circular dependencies when possible.
- If you need a value for a configuration that might change in a future version, initialize it with let instead of const to minimize refactoring headaches.
- Tools like TypeScript can add compile-time guarantees about const usage, but JavaScript engines implement runtime checks that can reveal issues in development environments.
Putting it all together with practical examples
Let us apply the const keyword in several small, real world patterns to reinforce the concept. In a function that computes a value once, declare the result with const and return it. When gathering configuration for a module, export a frozen configuration object to prevent accidental changes. In a React component, prefer const for props references that should not be reassigned within render. Finally, remember that const is a tool to express intent; combining it with clear naming, immutability patterns, and small, pure functions leads to safer, more predictable code.
Questions & Answers
What happens if I try to reassign a const variable?
Attempting to reassign a const binding results in a TypeError at runtime. The binding cannot be rebound within its scope. This helps prevent accidental value changes and makes the code behavior more predictable.
Reassigning a const variable causes a TypeError because its binding cannot be changed.
Can I mutate the contents of an object declared with const?
Yes. Declaring an object or array with const only prevents rebinds of the variable. You can still change properties or perform mutations on the contents. To prevent any changes, you would need to freeze the object.
Yes, you can mutate the contents of a const object, but you cannot rebind the variable to a different object.
What is the difference between const and let?
Const creates a non reassignable binding, while let allows reassignment within the same block. Both are block scoped, but only one of them guarantees that the binding will not change. Use const by default and switch to let when you need to reassign.
Const cannot be reassigned, while let can be reassigned within its block.
Does const enforce immutability of values?
No. const only prevents rebinding of the binding. If the value is an object or array, its contents can be changed. For true immutability you must use patterns like Object.freeze or immutable data structures.
No, const does not make values immutable; it only fixes the binding.
When should I use const in loops?
If the loop variable does not get reassigned inside the loop body, declare it with const. If you need to update the variable, use let. This makes the loop semantics clearer and helps prevent accidental reassignments.
Use const for loop variables that do not change; use let when you reassign.
How does const interact with function scope?
Constants declared with const are scoped to the block in which they are defined. They behave the same in functions as elsewhere, including temporal dead zones and the inability to rebind within that block. This helps maintain invariants in your function logic.
Const inside a function is block scoped and cannot be reassigned.
What to Remember
- Start with const by default for bindings you never reassign.
- Remember that const blocks reassignment, not mutation of contents.
- Use let when you know a value will change within a scope.
- Understand the temporal dead zone to avoid initialization errors.
- Guard against mutation with freezing when immutability is critical.