Detailed explanation
const and Object.freeze protect different things: const protects a variable binding, while Object.freeze protects an object's own properties. A binding is the association between a variable name and its value. After a const declaration is initialised, assigning another value to that name throws a TypeError. However, if the value is an object, its contents can still change. For example, const user = { name: 'Asha' }; allows user.name = 'Ravi', but user = {} fails. This distinction matters when discussing immutable data: a constant reference does not imply an immutable object.
Object.freeze(obj) operates on the object itself and returns that same object, not a copy. Internally, it prevents extensions and makes all existing own properties non-configurable; for data properties, it also sets writable to false. Consequently, properties cannot be added, deleted, or reassigned, and their descriptors cannot be freely redefined. The restriction applies through every reference to that object. Freezing does not protect the variable binding: let settings = Object.freeze({ mode: 'dark' }); still permits settings = { mode: 'light' }, because settings was declared with let.
Freezing is shallow. In const o = Object.freeze({ a: 1, n: { b: 2 } }), the property n cannot be replaced, but the object stored in n is not automatically frozen. Therefore, o.n.b = 9 works. The statement o.a = 9 is silently ignored in non-strict code but throws a TypeError in strict mode, including JavaScript modules. Reassigning a const binding, by contrast, throws regardless of strict mode. Failed mutation should therefore not be described as always ignored.
Using const and Object.freeze together provides a non-reassignable binding to a shallowly frozen object. This is useful for configuration objects and shared constants where accidental top-level changes should be prevented. For stronger guarantees, nested objects must also be frozen, with cycle detection when traversing arbitrary object graphs. Even then, freezing is not a universal immutability mechanism: accessor setters can still run, and objects such as Map retain mutable internal state. Interviewers usually look for the binding-versus-object distinction, shallow behaviour, and accurate handling of strict-mode failures.
Key points to remember
- const prevents reassignment of a binding, not mutation of the referenced object.
- Object.freeze returns the original object and restricts its own properties through every reference.
- Freezing prevents extensions and makes own properties non-configurable and data properties non-writable.
- Freezing is shallow: nested objects remain mutable unless separately frozen.
- Writing to a frozen data property throws in strict mode but is silently ignored in non-strict mode.
Common mistakes candidates make
- Claiming that declaring an object with const makes its properties immutable.
- Assuming Object.freeze recursively freezes nested objects or creates a new object.
- Saying frozen-property assignments are always ignored, without mentioning strict-mode TypeErrors.
Likely follow-up questions
How does Object.seal differ from Object.freeze?
Object.seal prevents adding or deleting own properties and makes existing properties non-configurable. Unlike Object.freeze, it leaves writable data properties writable; both operations are shallow.
How would you deeply freeze an object?
Recursively freeze each nested object as well as the root, tracking visited objects with a WeakSet to handle cycles. A robust implementation must consider symbol keys and accessors, and ordinary recursive freezing still does not stop mutations to Map or Set internal entries.
What happens when you freeze an array?
Its existing elements and length become non-writable, and new elements cannot be added. Methods such as push throw when they attempt prohibited changes, but objects stored inside the array remain mutable unless separately frozen.
Interview tip: Start with “const protects the binding; Object.freeze protects the object,” then demonstrate reassignment, top-level mutation, and nested mutation.
