Constant Variables in JavaScript, or: When "const" Isn't Constant
ECMAScript 2015 introduced the let
and const
keywords as alternatives to var
, which JavaScript has always had. Both let
and const
declare local variables with block scope rather than function scope. In addition, const
provides some notion of constancy, which let
doesn't.
Unfortunately, the name of the const
keyword might be misleading. In JavaScript, const
does not mean constant, but one-time assignment. It's a subtle yet important distinction. Let's see what one-time assignment means:
// We're declaring PI to be a constant variable.
const PI = 3.141592653589793;
// Any attempt to assign a new value to PI
// fails because PI is a constant variable.
PI = 0;
PI++;
// All of the variable declarations below fail
// because we can't declare a new variable with the
// same identifier as an existing constant variable.
var PI = 0;
let PI = 0;
const PI = 0;
However, variables declared using the const
keyword do not generally have a truly immutable value. Remember, const
does not mean "constant", it means one-time assignment. The part that's constant is the reference to an object stored within the constant variable, not the object itself. The following example illustrates the difference:
// We're declaring a constant variable
// to hold a settings object.
const settings = {
baseUrl: "https://example.com",
};
// Since `settings` is a constant variable,
// an attempt to assign a new value will fail.
settings = {};
// However, the object is **not** immutable.
// This means we can change its properties!
settings.baseUrl = "https://evil.example.com";
Declaring a variable to be constant doesn't make the objects it references immutable, as the above example shows. Object properties can change or be deleted altogether. The same goes for arrays assigned to a constant variable; Elements can be added, removed, reordered, or modified:
const numbers = [1, 2, 3];
numbers.push(4);
numbers.shift();
// numbers = [2, 3, 4]
For the sake of completeness, it is possible to create true constants in some cases. If a primitive value (such as a string, number, or boolean value) is assigned to a constant variable, that variable will be a true constant. Our PI
constant is an example for this. There's no way to modify the value of the numeric literal 3.141592653589793
after it has been assigned.
To make an object truly immutable, you can pass it to the Object.freeze
function to prevent any changes to its properties. Be aware that freeze
is shallow, so you'll have to recursively call it for nested objects if you want the entire object tree to be frozen. If you need immutable data structures, it might be safer and more convenient to use a library such as Facebook's Immutable.js which is specifically made for this purpose.