JS Tip of the Day: Freezing Objects

Freezing Objects
Level: Beginner

Just like you can prevent extensions in and seal in objects, you can also freeze them. When an object is frozen, extensions are prevented, existing properties are set to non-configurable and set to non-writable. Freezing is achieved with Object.freeze().

let obj = { existing: true };
Object.freeze(obj);
obj.prop = 'a new property'; // TypeError in strict mode
console.log(obj.prop); // undefined
delete obj.existing; // TypeError in strict mode
console.log(obj.existing); // true
obj.existing = false; // TypeError in strict mode
console.log(obj.existing); // true

Freezing an object locks the properties of an object completely so that no changes are allowed. As with preventing extensions and sealing, it doesn’t apply to inheritance so a new property could be added, removed, or changed if inherited.

Once you freeze an object, you can’t go back. But you can check to see if an object has been sealed using Object.isFrozen().

let obj = {};
console.log(Object.isFrozen(obj)); // false
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true

Of the different levels of object lockdown available (preventing extensions, sealing, freezing), freezing is likely going to be the most common as it helps enforce immutability in objects, a characteristic popular with the functional style of programming which has gained a lot of traction recently. Instead of modifying existing objects, you’d instead create new objects with the changed properties. By freezing an object you can ensure that it is immutable and a new object is required if changes are needed.

let user = Object.freeze({ first: 'Jane', last: 'Doe' });
// user.last = 'Smith' // not allowed
let marriedUser = {
  ...user, // copy all existing properties
  last: 'Smith' // specify changes
};

More info:

The example that you give:
let obj = {};
console.log(Object.isFrozen(obj)); // true
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // false
does not seem right. I tried this in the console of the latest version of Chrome it reports completely different results. The first one is false and the second one is true which is what you would expect.

@REB_412 Thanks for that! I thought I fixed it but must have forgotten (this was a copy-paste error from isExtensible() which has the opposite results with preventExtensions()). It should be fixed now.