Its my Code Blog

A JavaScript Const is not immutable

December 13, 2019

alt text

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: "🐩"}

We can also push another value to a JavaScript constant that contains an array.

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>)

Nicholas Murray
Stuff I've learnt and stuff I like