Most arrays in modern JavaScript are declared with const. That surprises people at first, because the arrays still change all the time. This lesson explains exactly what const locks, what it does not, and how to lock an array for real when you need to.
const means the variable will always point to the same array. The contents of that array can still change freely:
const cars = ["Saab", "Volvo"];
cars.push("BMW"); // allowed: changing contents
cars[0] = "Toyota"; // allowed: changing an element
cars.sort(); // allowed: rearranging
console.log(cars);
cars = ["Audi"]; // TypeError: Assignment to constant variable
const is a label glued permanently to one box. You can put things in the box, take things out, and rearrange them. You just cannot peel the label off and stick it on a different box.
Since you cannot reassign it to [], empty it in place instead:
const queue = ["a", "b", "c"];
queue = []; // TypeError
queue.length = 0; // works: removes every element
queue.splice(0); // also works
const list; // SyntaxError: Missing initializer in const declaration
const list = []; // correct
A const array follows the same block-scope rules as any const:
const colors = ["red"];
{
const colors = ["blue"]; // a different array, only inside this block
console.log(colors); // ["blue"]
}
console.log(colors); // ["red"]
const arrived in 2015. Before that, arrays were declared with var, and you will still see it in older code. The rules you learned in JS Scope apply to arrays too:
// var: no block scope
var list = ["a"];
{
var list = ["b"]; // the SAME variable, replaced
}
console.log(list);
A var array can even be used before the line that declares it (hoisting, from JS Hoisting):
cars = ["Saab", "Volvo"];
var cars; // allowed, but confusing
Redeclaring is the other big difference. var lets you declare the same name again anywhere. const does not allow it in the same scope, in either order:
var cars = ["Volvo"];
var cars = ["BMW"]; // allowed with var
const bikes = ["BMX"];
var bikes = ["Trek"]; // SyntaxError: Identifier 'bikes' has already been declared
{
const bikes = ["Trek"]; // allowed: a new block is a new scope
}
That SyntaxError stops the whole script before any of it runs, so the mistake cannot slip by unnoticed.
Only when the variable itself needs to point to a different array later, typically because you rebuild it with a method that returns a new array:
let visible = allItems;
if (onlyInStock) {
visible = visible.filter(item => item.stock > 0); // reassigned to a new array
}
Even this is often written with const by using a ternary:
const visible = onlyInStock ? allItems.filter(i => i.stock > 0) : allItems;
When an array must never change, such as a fixed list of options, freeze it:
const DAYS = Object.freeze(["Mon", "Tue", "Wed", "Thu", "Fri"]);
DAYS[0] = "Monday"; // ignored (TypeError in strict mode)
DAYS.push("Sat"); // TypeError: Cannot add property 5, object is not extensible
console.log(DAYS[0]); // "Mon"
Object.freeze locks the array's own slots, but objects inside it can still change. Object.freeze([{ n: 1 }])[0].n = 2 works. To lock everything, you would have to freeze each inner object too.
| Action | let | const | const + freeze |
|---|---|---|---|
| Change / add / remove elements | Yes | Yes | No |
| Point the variable at another array | Yes | No | No |
const by default. It prevents one class of bug (accidentally replacing the whole list) and tells readers the variable always refers to the same list.
const a = [1, 2]; Which line throws an error?
a.push(3);a[0] = 5;a = [3];a.length = 0;const locks the variable, not the array, so changing the contents is fine. Pointing a at a new array gives TypeError: Assignment to constant variable.What does this log?
var team = ["Ava"];
{
var team = ["Ben"];
}
console.log(team);
["Ben"]. var ignores blocks, so the inner line replaces the same variable. With const (or let) in both places, it would log ["Ava"].What does this log?
const DAYS = Object.freeze(["Mon", "Tue"]);
DAYS[0] = "Sun";
console.log(DAYS[0]);
Mon. The array is frozen, so the change is silently ignored (in strict mode it would throw a TypeError instead).const array, sort it, and change an elementlength = 0 and confirm it is []