In this article, we will see what is the problem with objects in JavaScript and why we need to “deep-freeze” an object in JavaScript. We will also learn how to “deep-freeze” an object in JavaScript.
Problem with Object in JavaScript:
We all know that JavaScript objects are mutable. How can we make them immutable? Define them as const but if we declare a JavaScript object as a const, it only prevents the object from getting reassigned as a whole. We can still reassign the properties and change their value.
Example 1:
Javascript
const obj1 = { key1: "val1" , key2: "val2" , key3: "val3" }; console.log( "Before Change" ); console.log(obj1); obj1.key1 = "val" ; console.log( "After Change" ); console.log(obj1); |
Output:
"Before Change"
{
key1: "val1",
key2: "val2",
key3: "val3"
}
"After Change"
{
key1: "val",
key2: "val2",
key3: "val3"
}
There are several methods that can be used to deep-freeze an object.
- Using Object.freeze()
- Using JSON.parse() and JSON.stringify()
- using Object.freeze() and Object.isFrozen()
We will explore all the above methods along with their basic implementation with the help of examples.
Approach 1 : Using Object.freeze()
We can use an Object.freeze() method provided by JavaScript to prevent the addition of new properties with updating and deleting of existing properties.
Example : In The example demonstrates how to use Object.freeze() to make an object immutable, preventing changes to its properties.
Javascript
const obj1 = { key1: "val1" , key2: "val2" , key3: "val3" } console.log( "Before Change" ) //before change console.log(obj1); Object.freeze(obj1); obj1.key1 = "val" ; console.log( "After Change" ) //after change console.log(obj1); |
Before Change { key1: 'val1', key2: 'val2', key3: 'val3' } After Change { key1: 'val1', key2: 'val2', key3: 'val3' }
Approach 2 : Using JSON.parse() and JSON.stringify():
The approach involves converting the object to a JSON string using JSON.stringify(), then parsing it back into a new object using JSON.parse(). This creates a deep-frozen object, making it immutable.
Example: The example showcases deep-freezing an object using JSON.parse() and JSON.stringify(),To deep-freeze the object, we first convert it to a JSON string using JSON.stringify(), and then parse it back into a new object using JSON.parse(). This creates a new object with the same structure as the original, but it is a completely independent copy and is now deep-frozen,After deep-freezing, any attempts to modify the properties of deepFrozenObj won’t have any effect because it is now immutable. The
Javascript
const obj1 = { key1: "val1" , key2: "val2" , key3: "val3" }; console.log( "Before Change" ); console.log(obj1); const deepFrozenObj = JSON.parse(JSON.stringify(obj1)); deepFrozenObj.key1 = "val" ; // This won't modify the deepFrozenObj deepFrozenObj.key2 = "newVal" ; // This won't modify the deepFrozenObj console.log( "After Change" ); console.log(deepFrozenObj); |
Before Change { key1: 'val1', key2: 'val2', key3: 'val3' } After Change { key1: 'val', key2: 'newVal', key3: 'val3' }
Approach 3: using Object.freeze() and Object.isFrozen()
The approach recursively deep-freezes an object and its nested properties using Object.freeze() and Object.isFrozen(). This makes the object and its properties immutable, preventing changes.
Example: The example demonstrates a recursive deep-freezing function using Object.freeze() and Object.isFrozen() to make an object and its nested properties immutable, preventing modifications.
Javascript
const obj1 = { key1: "val1" , key2: "val2" , key3: [ "val3" , "val4" , "val5" ] }; const deepFreeze = (obj1) => { Object.keys(obj1).forEach((property) => { if ( typeof obj1[property] === "object" && !Object.isFrozen(obj1[property]) ) deepFreeze(obj1[property]); }); return Object.freeze(obj1); }; deepFreeze(obj1); console.log( "Before Change" ); console.log(obj1); obj1.key3[0] = "val" ; obj1.key3[1] = "val" ; obj1.key3[2] = "val" ; console.log( "After Change" ); console.log(obj1); |
Before Change { key1: 'val1', key2: 'val2', key3: [ 'val3', 'val4', 'val5' ] } After Change { key1: 'val1', key2: 'val2', key3: [ 'val3', 'val4', 'val5' ] }