In this post, we will learn a couple of ways of creating immutable objects in JavaScript, as well what are the pros and cons of each approach. Object immutability will reduce side-effects and unpredictable behavior.
We will cover:
- const
- preventExtentions
- seal
- freeze
Note: this also applies for TypeScript
1. const
The first to come to mind is, of course, const
, const
prevents re-assign the object but the object's contents (e.g., its properties) can be altered.
Let's see the example:
const person = {
firstName: 'pera',
lastName: 'trta',
address: {
street: 'street'
}
};
// person = false; // re-assign is not allowed
person.firstName = 'pera pera'; // update is allowed
person.middleName = 'pt'; // add is allowed
person.address.street = 'street 123'; // update is allowed
delete person.lastName; // delete is allowed
2. preventExtentions
As we saw, const
has a drawback regarding object immutability. Another alternative is Object.preventExtensions()
a method which prevents adding new properties to the object (updating and deleting existing properties is still allowed).
const person = {
firstName: 'pera',
lastName: 'trta',
address: {
street: 'street'
}
};
Object.preventExtensions(person);
// true
console.log(Object.isExtensible(person));
// person = false; // re-assign is not allowed
person.firstName = 'pera pera'; // update is allowed
person.middleName = 'pt'; // add is not allowed
delete person.lastName; // delete is allowed
person.address.street = 'street 123'; // update is allowed *
person.address.newProperty = 7; // update is allowed *
* Please, keep reading, explanation is at the end of the post.
3. seal
Another Object's method is seal
. This one will prevent adding (sealing an object prevents new properties from being added) new and deleting existing properties to and from the object (updating existing properties is still allowed).
const person = {
firstName: 'pera',
lastName: 'trta',
address: {
street: 'street'
}
};
Object.seal(person);
// sealed objects are by definition non-extensible
console.log(Object.isExtensible());
// true
console.log(Object.isSealed());
// person = false; // re-assign is not allowed
person.firstName = 'pera pera'; // update is allowed
person.middleName = 'pt'; // add is not allowed
delete person.lastName; // delete is not allowed
person.address.street = 'street 123'; // update is allowed *
person.address.newProperty = 7; // but here add is allowed *
* Please, keep reading, explanation is at the end of the post.
4. freeze
Another Object's method is freeze
- freezes an object. A frozen object can no longer be changed; freezing an object prevents new properties from being added, updated or removed.
const person = {
firstName: 'pera',
lastName: 'trta',
address: {
street: 'street'
}
};
Object.freeze(person);
// freezed objects are by definition non-extensible
console.log(Object.isExtensible());
// true
console.log(Object.isFrozen());
// person = false; // re-assign is not allowed
person.firstName = 'pera pera'; // update is not allowed
person.middleName = 'pt'; // add is not allowed
delete person.lastName; // delete is not allowed
person.address.street = 'street 123'; // but here update is allowed *
person.address.newProperty = 7; // here add is allowed as well *
* So, what is going on lines with the asterisk sign?
The result of calling Object.preventExtensions(object)
, Object.seal(object)
, Object.freeze(object)
only applies to the immediate properties of object itself which means if the value of those properties are objects themselves (in our case property address
is an object), those objects are not affected by the methods. The solution for this issue will be in another post.
Thank you for reading!
Top comments (0)