You will understand why a JavaScript array declared with const can still be changed, and how to choose between const, let, and freezing when working with arrays.
What it is
In JavaScript, const creates a constant binding, not a constant value. When you write const a = [1], the name a cannot be reassigned to a different array. However, the array itself is an object, and its contents can still be mutated by methods such as push(), pop(), or direct index assignment.
A useful mental model is: const locks the variable name to one memory reference. It does not lock the object that the reference points to. Related terms include binding, mutation, reassignment, and immutability.
Why it matters
- It prevents accidental reassignment while still allowing normal array updates.
- It explains why code like
a.push(2)works even thoughais declared withconst. - It helps you avoid bugs when you need a truly immutable array.
- It supports safer defaults: use
constunless you need to reassign the variable. - It clarifies the difference between changing a variable and changing the data inside an object.
Syntax or steps
The smallest useful pattern is:
const items = [];
items.push("apple");
Step by step:
- Declare the array with
constso the variable cannot be reassigned. - Mutate the array using methods like
push(),splice(), or index assignment. - If you need to replace the whole array, use
letinstead ofconst. - If you need to prevent mutation, use
Object.freeze()or create a new array instead of changing the old one.
Example
const a = [1];
a.push(2);
console.log(a); // [1, 2]
a[0] = 99;
console.log(a); // [99, 2]
// a = [3]; // TypeError: Assignment to constant variable.
Part by part:
const a = [1]creates a constant variable namedathat points to an array.a.push(2)changes the contents of that array, so it is allowed.a[0] = 99also changes the contents, so it is allowed.a = [3]tries to makeapoint to a new array, so it throws aTypeError.
Common mistakes
- Mistake: Thinking
constmakes arrays immutable. Fix: Remember thatconstprevents reassignment, not mutation. - Mistake: Using
leteverywhere because you are unsure. Fix: Preferconstby default and switch toletonly when the variable must be reassigned. - Mistake: Using
Object.freeze()and expecting nested arrays to be frozen too. Fix:Object.freeze()is shallow; freeze nested objects separately or use immutable update patterns. - Mistake: Forgetting that array methods like
map()andfilter()create new arrays. Fix: If you want to avoid mutation, return a new array instead of changing the original.
When to use it
Use const for arrays when the variable should always refer to the same array, even if the array contents may change. Use let when you need to replace the entire array. Use Object.freeze() when you want to prevent mutation of the array itself.
| Pattern | Allows reassignment? | Allows mutation? | Best for |
|---|---|---|---|
const a = [1] | No | Yes | Normal arrays that may grow or change |
let a = [1] | Yes | Yes | Arrays that may be replaced entirely |
const a = Object.freeze([1]) | No | No for top-level array | Read-only arrays |
Practice
Guided exercise: predict the output.
const nums = [10];
nums.push(20);
nums = [30];
Expected result: the first two lines work, but the third line throws a TypeError because nums is a constant binding.
Challenge: rewrite the code so the array can be replaced with a new array.
let nums = [10];
nums.push(20);
nums = [30];
console.log(nums); // [30]
Quick check
Question: Why does const a = [1]; a.push(2); work?
Answer: Because const prevents reassigning a, but a.push(2) mutates the existing array object.
Summary
A const array in JavaScript is a constant reference, not a constant value. You can change the array contents while keeping the same variable binding, but you cannot point that variable to a new array.