Immutable Objects and much more in JavaScript.
Objects and arrays in JavaScript looks simple at the first glance but when you explore them deeply only then you get to know that there is a lot more going on then just simple push/pop and assigning a new value to an object.
First of all let's see what Immutable and mutable Arrays and Objects are.
Immutable Objects and arrays
In simple English, according to dictionary.com, the word Immutable means - not mutable; unchangeable; changeless i.e. an object with a fixed structure and properties whose values cannot be changed.
Let's first understand immutable objects with an example,
This is a simple nested object, now we'll se what immutable operations we can perform on this object.
Modify or add property
This is the standard way of mutating an object. But we have to do it in a immutable way so that the original object remains unchanged and for this we will use spread operator, similar to array, spreading the key-value pairs of the original object onto a new one.
The spread operator will spread the vehicles object into the new object newVehicles without mutating the original object. Here we are also adding a new key of tata and also we can modify the existing keys all while the original objects remains unchanged.
Modifying or adding property in nested objects
Now there is something interesting in nested objects. Did you notice something wrong in the last code snippet that i wrote? If you missed it then don't worry because I am gonna explain what was wrong.
In the above code snippet, if we were to console the object, what do you think the output will be?
This will be the output. And you can clearly see that the nested tata object is outside the nested car object, but why? Because we did spread the vehicles object but we didn't spread the nested object inside the vehicles object i.e. car. Let's see how we can do that.
And this time the output will be this,
Why? Because this time we did spread the vehicles object but we also spread the car object and then added a new key to that. So this is how spread operators work.
This is how we can modify an object without mutating the original object.
Frozen Objects
By default, objects are mutable. This means once they're created, you can add a new property to them, modify the value of an existing property, or delete a property.
There can arise some situation where you may not want an object to change. So you'll make it immutable. And when you make an object immutable, you can't add a new property to it, modify it, or delete an existing property.
This is what Frozen Objects are.
How to create frozen Objects?
We can use the Object.freeze() method. This will freeze the object. Once we freeze an object we can no longer change the object, new properties cannot be added, existing properties cannot be removed.
Let's understand this with an example.
Here we created a new object named as student that contains two properties. We used the Object.freeze() method to freeze the object. This method takes one argument i.e. the object that we want to freeze.
Now the object is frozen, let's try to modify it.
Here, after freezing the student object when we try to change the name property it remains unchanged because we have frozen the object so we can no longer make any change to it.
The Object.freeze() method will only throw error in strict mode.
But wait, doesn't const do the same work?
Not exactly.
See, we use const to define a constant variable which we cannot reassign.
Let's take an example.
You can see that we can easily change a key's value or add a new ket to the object defined with the const keyword. But when we try to assign a whole new object to it then it will throw error. Let's see.
Here, we are assigning a whole new object to the obj variable. So, it will throw an error saying that you cannot assign a value to a constant variable.
Object.freeze() is shallow
As we know that a JavaScript object can have multiple object inside it. It can go many levels deep.
When we freeze an object using Object.freeze(), it only freezes the object to the first level. Let's understand this.
Now, students.student1.friends.friend1.name will be equal to Vinit and not Rahul. Just try to run this code in your code editor and you'll understand what I am saying.
So how do we make nested objects also frozen?
We can do that using recursion. Recursion is a methodology that uses a procedure, function, or algorithm to call itself.
Let's see how.
This deepFreeze function will make the deepest level of the object also frozen and we can no longer change anything in this.
There are also a few more methods fairly similar to Object.freeze(),
=> 1. Object.seal() – We can not add a new property or delete existing properties of an object sealed with this method. But we can still update the value of existing properties.
=> 2. Object.preventExtensions() – This method prevents new property creation. But you can update and delete existing properties.
Keep coding!! Keep drinking water!!