Make Object Immutable
Write deepFreeze(obj) that freezes an object and everything nested inside it, then returns the same object.
After freezing, writing to a property at any depth must not change it. A structure that contains itself must not recurse forever.
Examples
const config = deepFreeze({ api: { retries: 3 } });
config.api.retries = 99;
config.api.retries;3Constraints
- Values are objects, arrays and primitives
Notes
- In sloppy mode a write to a frozen property fails silently; only strict mode throws.
- Freeze before recursing and `Object.isFrozen` becomes your cycle guard for free.
Hints
Make Object Immutable (reference solution)
One way to do it. The Editorial tab walks through why it is written this way.
Solution
1function deepFreeze(obj) {
2 if (obj === null || typeof obj !== 'object' || Object.isFrozen(obj)) return obj;
3 Object.freeze(obj);
4 Object.getOwnPropertyNames(obj).forEach((key) => deepFreeze(obj[key]));
5 return obj;
6}Editorial: Make Object Immutable
Freeze is shallow
Object.freeze stops writes to an object's own properties and nothing deeper. A frozen config with a nested object is still fully mutable one level down, which makes it a false guarantee.
Approach
Freeze, then recurse.
Implementation
function deepFreeze(obj) { if (obj === null || typeof obj !== 'object' || Object.isFrozen(obj)) return obj; Object.freeze(obj); Object.getOwnPropertyNames(obj).forEach((key) => deepFreeze(obj[key])); return obj; }
Worth knowing
Order matters. Freezing before recursing means a self-referencing object is already frozen when the walk reaches it again, so Object.isFrozen doubles as the cycle guard and no extra bookkeeping is needed.
In sloppy mode a write to a frozen property fails silently — no error, no change — which is why this surprises people. Only strict mode throws. Deep-freezing a large object is also not free: every nested object is walked and frozen once, and freezing is permanent.