Immutability in JavaScript

Change is good. But, this is not always true and developers can bear testimony to this as they ironically strive for a state of no change or immutability.

Let’s start with the basics first – what is Immutability?

Literally speaking, immutable means something that can not be changed.

In web development, immutability is the property that defies change. This is not usually easy to achieve.

You might be wondering why do we need it? The reason is simple – if you know there is only one function you want to achieve with a code, you would like it to remain the same forever. 

So it will make sense if you want to save it against any error or bugs that arise when you put the complete code together.

There are many other more benefits too:


It helps to secure sensitive information against any changes and malpractices like the name of the owners of properties or things.


This is possibly the best benefit of immutability as the values can not be changed even if accessed from multiple threads. However, even if they are changed, it will create a new string.

Enables reuse

The final and the initial state of your application always varies. Going for the mutations will make tracking the changes resulting in the errors difficult. But immutability can make them easy, and also makes sure there are no drawbacks.

Primitives & Objects

Here is the good part, all JavaScript primitives are immutable. These include undefined, null, boolean, number, string, and symbol values.

On the other hand side, objects are mutable. Everything not included in the primitive is considered an object.

How to Achieve Immutability in JavaScript?

Use Const

This is considered the easiest way to achieve mutability but as java is highly mutable, this is often not enough.

However, be mindful that it will not completely prevent mutation but will only avert re-assignment. So it does not solve the problems as it allows you to re-assign the shared variables, leading to changes

  • Strong Immutability

When nothing can be changed in regards to an object, it is complete immutability.

  • Weak Immutability

As the name suggests, it is not strong enough as there is still scope for change. Herein though the values can be changed, the properties can not be changed.


One of the commands that can help you secure your code against unnecessary changes is Object. freeze()

As is clear from the name, it freezes or stops your object at its current state. You can also use it in the scenarios where you want to let the values change but seek immutability at the end.

let teaPot = {};




   {value: ‘blue’, writable: false}


teaPot.age = 3;

teaPot.age = 4;

teaPot.color = ‘purple’;


teaPot.color = ‘green’;

teaPot.age = 5;

delete teaPot.color;


On using, the above set, the result will be:

{age: 4, color: “blue”}


Object Define Property

This is a good option for strong mutability as it lets you define the mutability stature. 

It also comes with the freedom of setting both the properties and value to ‘read-only.’

Although Object.defineProperty() does not let you change anything you have written, you can add more properties to the object.

It would look something like this:

In console.log(), it will show something like this:

{ color: “blue” }

Moreover, if you use the delete command, it will simply be ignored and you can expect:

Here, the color will be strongly mutable as it will not change. The output will look something like: {age: 4, color: “blue”}


Spread Syntax …

It is an easy way for generating new objects for making changes rather than changing the original object itself.

Herein you can copy the existing values to a new one. It lets you extend arguments for iterable objects. You can use a spread syntax ( …) inside a new array or object literals. This lets you copy the properties of existing values into the new value.

It will make it super easy to add new values to an array, add new key-value pairs and modify a key-value pair on an object.

Ramda lens

They consist of two pairs of functions – a getter used for a focus element ‘A’ that comes from a source ‘S’

and a setter that updates ‘A’ by generating a new object, in turn ensuring immutability.

Additionally, it can be easily implemented, just like a single function.’

Here, you generate a new lens using lensIndex and lensProp. After this, you will be able to generate new data with set and over methods. But like standard Object/Array spreads, these new values will also share the non-updated references with the old values.


Immer uses a proxy constructor to create a draft version of the original object. It refers to the library by Michael Westrate. So if you do not want to import robust tools or deal with complex API for immutability, this can b your  go-to option.

Here is quick  example :

It gives you the freedom to freeze the new properties in the development phase itself, making it a time saving and smart choice.