A JavaScript Const is not immutable
December 13, 2019
A JavaScript Const is not immutable
immutable - unchanging over time or unable to be changed
A JavaScript Const is a variable that cannot be reassigned?
In the following example we declare a javaScript constant variable DOG and assign it the value βπβ. When we try to
reassign its value to βπ©β it creates an error Assignment to constant variable
. This is because we are
trying to change its read-only reference to a value or in other words reassigning its value.
const DOG = 'π';
console.log(DOG);
π
DOG = 'π©';
β Uncaught TypeError: Assignment to constant variable.
Are JavaScript Consts then immutable?
The previous example would lead us to believe that constants are in fact immutable as we received an error saying that
we could not assign another value to a constant variable. But in the example below, we create a const object PET_DOG
and then update its breed property and we do not receive an error.
const PET_DOG = {
name: 'Rover',
breed: 'π'
};
console.log(PET_DOG);
{name: "Rover", breed: "π"}
PET_DOG.breed = 'π©';
console.log(PET_DOG);
{name: "Rover", breed: "π©"}
const DOGS = ['π', 'π©'];
console.log(DOGS);
(2)Β ["π", "π©"]
DOGS.push('πΊ');
console.log(DOGS);
(3) ["π", "π©", "πΊ"]
Can we create a JavaScript Const that references objects or arrays immutable?
We can use the Object.freeze() method to freeze an object or array (in this case) to make the const reference immutable.
// error TS2339: Property 'push' does not exist on type 'ReadonlyArray<string>'.
// VM708:2 Uncaught TypeError: Cannot add property 3, object is not extensible at Array.push
const FROZEN = Object.freeze(['π¨', 'βΈοΈ', 'βοΈ']);
console.log(FROZEN);
(3)Β ["π¨", "βΈοΈ", "βοΈ"]
FROZEN.push('βοΈ');
β Uncaught TypeError: Cannot add property 3, object is not extensible
at Array.push (<anonymous>)
So what happens if we freeze an object that contains an array property
In the example below we freeze our FROZEN_YOUGART
Const object and then try to push to its array property.
But we can see that we can push items to the array as the array can be mutated. This is because Object.freeze
is shallow. This means that the Const is frozen but its contents are not.
const FROZEN_YOUGART = Object.freeze({
ingredients: ['π₯', 'π¦']
});
console.log(FROZEN_YOUGART);
{ingredients: Array(2)}
ingredients: (2) ["π₯", "π¦"]
__proto__: Object
FROZEN_YOUGART.ingredients.push('π');
console.log(FROZEN_YOUGART);
{ingredients: Array(3)}
ingredients: (3) ["π₯", "π¦", "π"]
__proto__: Object
So what happens if we instead deep freeze an object that contains an array property
In the example below we deep freeze our DEEP_FROZEN_YOUGART
Const object and then try to push to its array property.
Now we canβt push items to the array as the array canβt be mutated. This due to using Object.freeze on the object and
also on its ingredients array property.
// This does not work as the array contents can't be mutated as Object.freeze is applied to inner objects
// VM981:4 Uncaught TypeError: Cannot add property 2, object is not extensible
// at Array.push (<anonymous>)
const DEEP_FROZEN_YOUGART = Object.freeze({
ingredients: Object.freeze(['π₯', 'π¦'])
});
console.log(DEEP_FROZEN_YOUGART);
{ingredients: Array(2)}
ingredients: (2) ["π₯", "π¦"]
__proto__: Object
DEEP_FROZEN_YOUGART.ingredients.push('π');
β Uncaught TypeError: Cannot add property 2, object is not extensible
at Array.push (<anonymous>)