What is `Object.freeze()` for?
Topics
JavaScript
TL;DR
Object.freeze() makes an object non-extensible and changes its own properties so they cannot be removed or reconfigured; data properties also become non-writable. This is a shallow operation: nested objects and internal state such as a Map's entries can still change. Invalid writes throw in strict mode and otherwise usually fail silently.
const obj = { name: 'John' };Object.freeze(obj);obj.name = 'Doe'; // This will not change the name propertyconsole.log(obj); // { name: 'John' }
What is Object.freeze() for?
Object.freeze() prevents additions, removals, reconfiguration, and writes to an object's own data properties. It is useful as a shallow guard against accidental mutation, but it does not make an arbitrary object graph deeply immutable.
How to use Object.freeze()
To use Object.freeze(), pass the object you want to freeze as an argument to the method. Here is a basic example:
const obj = {name: 'John',age: 30,};Object.freeze(obj);obj.name = 'Doe'; // This will not change the name propertyobj.gender = 'male'; // This will not add a new propertydelete obj.age; // This will not delete the age propertyconsole.log(obj); // Output: { name: "John", age: 30 }
Characteristics of a frozen object
- Shallow integrity: The frozen object's own data properties cannot be changed, added, or removed. Referenced objects are unaffected.
- Non-extensible: A frozen object is also non-extensible, meaning you cannot add new properties to it.
- Non-configurable: The properties of a frozen object become non-configurable, meaning you cannot change property descriptors.
Use cases for Object.freeze()
- Constants: When you want to create a constant object that should not be modified.
- Data integrity: Ensuring that an object remains unchanged throughout the lifecycle of an application.
- Defensive programming: Catching or preventing accidental writes. Freezing is not a security boundary when untrusted code can access nested values or other mutable capabilities.
Limitations
Object.freeze()only makes the object itself immutable. If the object contains nested objects, those nested objects are not frozen and can still be modified.- To deeply freeze an object, you would need to recursively apply
Object.freeze()to all nested objects.
const deepFreeze = (value, seen = new WeakSet()) => {if ((typeof value !== 'object' && typeof value !== 'function') ||value === null) {return value;}if (seen.has(value)) return value;seen.add(value);for (const key of Reflect.ownKeys(value)) {deepFreeze(value[key], seen);}return Object.freeze(value);};const nestedObj = {name: 'John',details: {age: 30,address: '123 Street',},};deepFreeze(nestedObj);nestedObj.details.age = 31; // This will not change the age propertyconsole.log(nestedObj); // Output: { name: "John", details: { age: 30, address: "123 Street" } }
Further reading
- MDN Web Docs on Object.freeze()
- JavaScript.info on property flags and descriptors
- MDN: Deep freezing
Exercises
Check your understanding
Beta