In Javascript, objects and arrays are mutable, primitive values are not. This means we can change an object (or array) anytime we want. But what if for some reason we want to stop this from happening and make the object immutable?
One way we we can achieve this is by using the freeze()
method.
A frozen object can no longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. In addition, freezing an object also prevents its prototype from being changed. freeze() returns the same object that was passed in.
Some code illustrating the usage of this method would look something like this:
const objectExample = {
prop1: 42,
prop2: "Jack"
};
// by default, we can modify the object's properties as we want
objectExample.prop1 = 100;
console.log(objectExample.prop1) // prints 100
// now let's freeze the object
Object.freeze(objectExample);
objectExample.prop2 = "Alice" // will throw an error in strict mode but fail silently in non-strict mode
console.log(objectExample.prop2); // prints "Jack", since we couldn't change the value of the prop
Something to keep in mind is that if the frozen
object has properties with objects as values, those objects can be changed unless we also froze them. This means we only achieved a shallow freeze
. To make objects immutable by freezing all their properties, including the ones that store other objects as values, we must do a deep freeze
- that is freezing the children objects before freezing the parent object, using recursion
.
The function below is just and example. You can name yours as you wish. Be careful when freezing objects as values of properties so you don't freeze something that shouldn't become immutable.
const theObject = {
x: 1,
z: 2,
y: {
a: "Hello",
b: "World"
}
}
const deepFreeze = (obj) => {
const propNames = Object.getOwnPropertyNames(obj)
for (const name of propNames) {
const value = obj[name];
if (value && typeof value === "object") {
deepFreeze(value);
}
}
return Object.freeze(obj);
}
deepFreeze(theObject);
theObject.y.a = 456; // the value can't be changed
console.log(theObject.y.a ); // Hello
Image source: Caspar Camille Rubin/ @casparrubin on Unsplash
Top comments (6)
Yeah the deep freeze is the concern and forces use if immutable.js. I mean when you apply .freeze() its assumed the whole object got locked but its not so and it also impact some performance
Got burned by the deep vs. shallow freeze thing once, great explanation!
“What people don’t know about immutable objects in JavaScript” by pandaquests link.medium.com/BKO0IIZeFab
Thank you for sharing.
How so?