Prevent Objects from Modification in JavaScript

Learn how to prevent objects from modification in JavaScript. This tutorials will help you prevent modification of nested objects/arrays and addition of new properties to the object.

Some of the biggest problems with JavaScript come from the flexibility it provides to developers. One such problem is the ability to modify arguments inside a function which in turn modifies the original parameter.

This is a fairly common practice in JavaScript, but not something that should be appreciated. Ideally, we should be writing pure functions that take in some arguments and return some value, without causing side effects.

Since, javascript allows you to modify objects inside functions there should be a provision to prevent anyone from modifying objects in JavaScript. In this article we will be going through a simple utility that will allow you to build objects which can’t be modified.

Before, we jump onto our solution let us evaluate a few options that we have with us in order to prevent javascript objects from getting modified.

  1. Prevent Extensions: The very first option that we have with us is an utility function named Object.preventExtensions. This utility will prevent addition of new properties to an object. But, updating properties and deleting them is allowed.
const user = {
    "id": 1, 
    "firstName": "Dinesh", 
    "lastName": "Verma"
};

// The below operation will block addition of new properties to user object
Object.preventExtensions(user);

// The below action won't cause an error, but won't work as expected.
user.address = "User's address";

user.firstName = "New FirstName";
delete user.lastName;

console.log(user);
  1. Seal: This utility function will prevent addition of new properties and deletion of existing properties. You can still update existing properties.
const user = {
    "id": 1, 
    "firstName": "Dinesh", 
    "lastName": "Verma"
};

// The below operation will seal the object
Object.seal(user);

// Not allowed operations
user.address = "User's address";
delete user.lastName;

// Allowed operations
user.firstName = "New FirstName"

console.log(user);
  1. Freeze: This is so far the best option we have when it comes to preventing update of objects in Javascript. This utility will prevent anyone from updating, deleting and adding new properties to an object.
const user = {
    "id": 1, 
    "firstName": "Dinesh", 
    "lastName": "Verma"
};

Object.freeze(user);

// Not allowed operations
user.address = "User's address";
delete user.lastName;
user.firstName = "New FirstName"

console.log(user);

From first look you may think that freeze if the best option that we have, but let’s see what happens when we introduce nested objects.

const user = {
    "id": 1, 
    "firstName": "Dinesh", 
    "lastName": "Verma",
    "address": {
        "city": "Bangalore",
        "state": "Karnataka"
    }
};

Object.freeze(user);

// You can perform these operations
user.address.pincode = "560000";
user.address.state = "New State";
delete user.address.city;

console.log(user);

As, you can see from the sample code above freeze doesn’t work on nested objects. Now let’s fix this problem.

The below utility takes in an object and returns an object which has all its nested objects frozen. This way you can get an object which can’t be modified in any way possible.

function deepFreeze(obj) {
    Object.keys(obj).forEach((key) => {
        if(typeof obj[key] === "object" && !Object.isFrozen(obj[key])) {
            deepFreeze(obj[key]);
        }
    })

    return Object.freeze(obj);
}

The above deepFreeze function takes in an object and iterates over all its properties and check if the property contains an object or not. If that property contains an object, then we recursively freeze that object as well. So, ultimately we get an object which is frozen and all its nested properties are frozen as well.