Object.freeze vs Object.seal

Abhay Jain
4 min readJan 13, 2021

--

Object.freeze()

Object.freeze takes an object as an argument. Note that it modifies the object you pass as an argument. It does not copy the object and create a new one.

So what does it mean for the object?

  • You can’t add new properties to the object
  • You can’t modify the properties if they are not objects or arrays themselves. (More on this later)
  • You can’t delete properties from the object
let objectToFreeze = {
age: 28,
name: "Damien",
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};

Object.freeze(objectToFreeze);

delete objectToFreeze.age;
objectToFreeze.name = "Ben";
objectToFreeze.pets.push("Grenade");
objectToFreeze.sibling.age = 26;
objectToFreeze.lastName = "Cosset";

With the description I just gave you, you should guess what the object will look like now:

console.log(objectToFreeze)

// objectToFreeze :
{ age: 28,
name: 'Damien',
pets: [ 'Symba', 'Hades', 'Kiwi', 'Grenade' ],
sibling: {
age: 26,
name: 'Corentin'
}
}

The delete failed, modifying the name property failed, and adding the lastName property failed. But modifying the array and the nested sibling object worked.

Note: If you are not in strict mode, it will fail silently. In strict mode, you will get TypeErrors

Shallow freeze

What we have when we call Object.freeze is a shallow freeze. We only freeze what is directly attached to the object. Properties inside objects and arrays are not concerned.

To make the entire object and everything inside immutable, you have to call Object.freeze() on every element.

let allYouCanFreeze = (obj) => {
// Retrieve the properties names
let propNames = Object.getOwnPropertyNames(obj);

// Loop through the properties
// If typeof is "object", meaning an array or object, use recursion to freeze its contents.
for (let name of propNames) {
let value = obj[name];
obj[name] =
value && typeof value === "object" ? allYouCanFreeze(value) : value;
}

// Finally, freeze the main object
return Object.freeze(obj);
};

Let's use it on our first object:

let objectToFreeze = {
age: 28,
name: "Damien",
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};

allYouCanFreeze(objectToFreeze);

// Now we can't touch the pets array and the sibling object

objectToFreeze.age = 26; // Now, fails.
objectToFreeze.pets.push("Grenade"); // Now, fails

Great! Now, our sibling object and our pets array can't be modified.

Object.isFrozen

To know if an object is frozen, you can use Object.isFrozen():

Object.isFrozen(objectToFreeze); // === truelet unfrozenObj = { a: 42 };
Object.isFrozen(unfrozenObj); // === false

Object.seal

Object.seal(), like the freeze method, takes a object as an argument. Object.seal is a softer version of Object.freeze.

  • You can’t remove or add elements to the object.
  • You can modify existing properties.
let objectToSeal = {
name: "Damien",
age: 28,
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};
Object.seal(objectToSeal);

Pretty straightforward huh? Let’s try to modify this object now:

delete objectToSeal.name;
objectToSeal.age = 56;
objectToSeal.lastName = "Cosset";
objectToSeal.sibling.age = 45;
objectToSeal.pets.push("Grenade");

Maybe you already guessed what should happen 😉

//objectToSeal new contents{
name: 'Damien',
age: 56, //modifying worked
pets: ['Symba', 'Hades', 'Kiwi', 'Grenade'], // push worked
sibling: {
age: 45, // Modifying worked
name: 'Corentin'
}
}
// adding and deleting failed!

Notice that just like Object.freeze, Object.seal will fail silently in non-strict mode and throw a TypeError in strict mode.

Object.isSealed

We also have a method to know if an object is sealed. Quite explicit, we can call Object.isSealed to know that:

Object.isSealed(objectToSeal); // === truelet notSealedObj = { a: 54 };
Object.isSealed(notSealedObj); // === false

What about const?

You might be tempted to look at Object.seal and Object.freeze and compare them to const. Remember that they are different concepts. Object.freeze and Object.seal apply on the values of an object, and const applies on the binding. Object.freeze makes an object immutable. const creates immutable binding. Once you assign a value to a variable, you can’t assign a new value to that binding.

What about prototypes?

One last thing I need to mention: prototypes. When it comes to Object.freeze and Object.seal, know that you also can’t change their prototypes once they are frozen or sealed.

let freezeThat = {
name: 'Damien'
}
let sealThis = {
age 28
}
Object.freeze(freezeThat)
Object.seal(sealThis)
// These two lines will fail!
Object.setPrototypeOf(freezeThat, {x: 26})
Object.setPrototypeOf(sealThis, {alive: true})

setPrototypeOf is used to change the prototype of an object. When the object is sealed or frozen, you will not be able to do that. As always, in non-strict mode, it will fail silently. In strict mode, you will see a TypeError: Object is not extensible.

--

--

Abhay Jain

Developer with 3 yrs of industrial experience in developing scalable web applications.