In this section, we will look at how to make an object immutable in Javascript. We will first look at the freeze() method and later discuss the seal() method and how they help make an object immutable.
Before looking at how to make an object immutable in Javascript, first, let us understand what mutable and immutable objects are.
In mutable objects, we can change the state of the object. Whereas, in immutable objects, we are not allowed to change the state of the object.
"use strict";
let employee = {
firstName: "Mickey",
lastName: "Mouse",
age: 10
};
// Mutable object
employee.firstName = "Donald";
console.log(employee); // {firstName: "Donald", lastName: "Mouse", age: 10}
In the above example, we have created an object employee
with properties firstName
, lastName
and age
. If we want to change the value of any of the properties, Javascript allows us to do so.
For example, in our case, we have changed the value of firstName
from Mickey
to Donald
. The object employee
is a mutable object where we can change the properties.
However, Javascript allows us to make an object immutable if we want to. Let us look at how we can do so.
Make an object immutable using Object.freeze()
The Object.freeze()
method is used to freeze an object. By freeze, we mean you cannot change the existing properties of the object, add new properties or even delete any properties.
Let us make use of the same above example we have discussed above and apply the freeze()
method.
"use strict";
let employee = {
firstName: "Mickey",
lastName: "Mouse",
age: 10
};
employee.firstName = "Donald";
console.log(employee); // {firstName: "Donald", lastName: "Mouse", age: 10}
// freeze the employee object
Object.freeze(employee);
employee.firstName = "Mickey"; // Uncaught TypeError
Here, we have frozen the employee
object. Hence, if we try to change the firstName
property it throws an error: Uncaught TypeError: Cannot assign to read only property 'firstName' of object '#<Object>'
.
You are not allowed to add a new property to an immutable object. For example, if try adding a property department
to employee
it throws an error Uncaught TypeError: Cannot add property department, object is not extensible
.
employee.department = "Accounting"; // Uncaught TypeError
Similarly, you cannot delete a property from an immutable object.
delete employee.age; // Uncaught TypeError
The error reads Uncaught TypeError: Cannot delete property 'age' of #<Object>
.
Object.seal() method
The Object.seal()
method seals the object in a way that you cannot add new properties to it nor delete any existing properties. However, you are allowed to make changes to the existing properties.
"use strict";
let employee = {
firstName: "Mickey",
lastName: "Mouse",
age: 10
};
// Seal the employee object
Object.seal(employee);
employee.firstName = "Donald";
console.log(employee); // {firstName: "Donald", lastName: "Mouse", age: 10}
//add a new property
employee.department = "Accounting"; // Uncaught TypeError
//delete an existing property
delete employee.age; // Uncaught TypeError
Object.freeze() vs Object.seal()
In seal()
method we are allowed to change the values of existing properties. But, when we use the freeze()
method, we cannot change the existing properties. For example,
"use strict";
let employee = {
firstName: "Mickey",
lastName: "Mouse",
age: 10
};
// Seal the employee object
Object.seal(employee);
employee.firstName = "Donald";
console.log(employee); // {firstName: "Donald", lastName: "Mouse", age: 10}
However, if we tried the same using the freeze()
method, we will encounter an TypeError.
"use strict";
let employee = {
firstName: "Mickey",
lastName: "Mouse",
age: 10
};
// Freeze the employee object
Object.freeze(employee);
employee.firstName = "Donald"; // Uncaught TypeError
The property firstName
is a read-only property in this case and we cannot change its value.
Setting the writable attribute of a property
There are might be a case where you want to only make certain properties in an object immutable. To do this we can make use of the writable
attribute.
For example, in our employee
object we don’t want to change the firstName
but we want to be able to change the lastName
and age
of the object.
"use strict";
let employee = {
firstName: "Mickey",
lastName: "Mouse",
age: 10
};
Object.defineProperty(employee, 'firstName', {
writable: false
});
// allowed
employee.age = 20;
console.log(employee); // {firstName: 'Mickey', lastName: 'Mouse', age: 20}
// Not allowed
employee.firstName = "Donald"; // Uncaught TypeError
We make use of the defineProperty
method of the Object
and set the firstName
property’s writable
attribute as false
. This way we can make the a specific property immutable.