Skip to main content

Make Object Immutable - Solution & Explanation

MediumPremiumFree on FleetCode5 min read
Practice this problem

Problem Statement

Write a function that takes an object obj and returns a new immutable version of this object.

An immutable object is an object that can't be altered and will throw an error if any attempt is made to alter it.

There are three types of error messages that can be produced from this new object.

  • Attempting to modify a key on the object will result in this error message: `Error Modifying: ${key}`.
  • Attempting to modify an index on an array will result in this error message: `Error Modifying Index: ${index}`.
  • Attempting to call a method that mutates an array will result in this error message: `Error Calling Method: ${methodName}`. You may assume the only methods that can mutate an array are ['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse'].

obj is a valid JSON object or array, meaning it is the output of JSON.parse().

Note that a string literal should be thrown, not an Error.

 

Example 1:

Input: 
obj = {
  "x": 5
}
fn = (obj) => { 
  obj.x = 5;
  return obj.x;
}
Output: {"value": null, "error": "Error Modifying: x"}
Explanation: Attempting to modify a key on an object resuts in a thrown error. Note that it doesn't matter that the value was set to the same value as it was before.

Example 2:

Input: 
obj = [1, 2, 3]
fn = (arr) => { 
  arr[1] = {}; 
  return arr[2]; 
}
Output: {"value": null, "error": "Error Modifying Index: 1"}
Explanation: Attempting to modify an array results in a thrown error.

Example 3:

Input: 
obj = {
  "arr": [1, 2, 3]
}
fn = (obj) => { 
  obj.arr.push(4);
  return 42;
}
Output: { "value": null, "error": "Error Calling Method: push"}
Explanation: Calling a method that can result in a mutation results in a thrown error.

Example 4:

Input: 
obj = {
  "x": 2,
  "y": 2
}
fn = (obj) => { 
  return Object.keys(obj);
}
Output: {"value": ["x", "y"], "error": null}
Explanation: No mutations were attempted so the function returns as normal.

 

Constraints:

  • obj is a valid JSON object or array
  • 2 <= JSON.stringify(obj).length <= 105

Approach Overview

Problem Overview: The task is to make a JavaScript object completely immutable. After the transformation, neither the object nor any nested objects or arrays inside it should allow modifications such as property updates, additions, or deletions.

Approach 1: Shallow Freeze with Object.freeze() (O(n) time, O(1) space)

The simplest idea is calling Object.freeze(obj). This prevents modification of the object's top-level properties. Any attempt to assign new values, delete properties, or extend the object fails in strict mode. However, this approach is only shallow. Nested objects and arrays remain mutable because Object.freeze does not recursively traverse the structure. This method works only when the object contains primitives or when deep immutability is not required.

Approach 2: Recursive Deep Freeze (DFS Traversal) (O(n) time, O(h) space)

The correct solution walks through the object recursively and freezes every nested structure. Start by iterating over each property using Object.keys() or a for...in loop. When a value is itself an object or array, recursively apply the same freezing logic before freezing the current object. This forms a depth-first traversal of the object graph. Each object is visited once, giving O(n) time complexity where n is the total number of nested objects and properties. The recursion stack consumes O(h) space where h is the maximum nesting depth.

This approach guarantees deep immutability. Arrays, nested objects, and complex structures become fully locked after processing. The technique mirrors classic recursive traversal patterns used in recursion and tree-style object processing in JavaScript.

Approach 3: Iterative Deep Freeze with Stack (O(n) time, O(n) space)

An alternative avoids recursion by using an explicit stack or queue. Push the root object onto a stack, then repeatedly pop elements and freeze them. Before freezing, scan their properties and push any nested objects or arrays onto the stack. This produces the same behavior as DFS but avoids recursion depth limits. The tradeoff is additional auxiliary memory because the stack may temporarily hold many objects.

Recommended for interviews: The recursive deep freeze approach is the expected solution. It demonstrates understanding of object traversal, recursion, and how JavaScript immutability works internally with Object.freeze. Mentioning the shallow-freeze limitation shows conceptual clarity, while implementing the recursive version shows practical skill working with nested structures and object manipulation.

Solution

Code

TypeScript

Try this approach in the editor →

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Shallow Freeze using Object.freezeO(n)O(1)When the object has no nested objects or deep immutability is unnecessary
Recursive Deep Freeze (DFS)O(n)O(h)Best general solution for deeply nested objects and arrays
Iterative Deep Freeze using StackO(n)O(n)Useful when recursion depth could exceed call stack limits

Video Solution

Don't Make This Coding Interview Mistake! | Jewels and Stones - Leetcode 771 • Greg Hogg • 443,129 views views

Watch 9 more video solutions →

Frequently Asked Questions

Is Make Object Immutable easy or hard?
The problem is typically rated Medium because it requires understanding the difference between shallow and deep immutability. Implementing recursive traversal correctly for nested objects and arrays is the main challenge.
Make Object Immutable Python/Java solution
The concept can be implemented in other languages using immutable wrappers. Python often uses tuples, frozenset, or custom recursive freezing logic, while Java uses unmodifiable collections. The JavaScript version relies on Object.freeze combined with recursive traversal.
How to solve Make Object Immutable in O(n)?
Perform a depth-first traversal of the object. For each property, check if the value is an object or array and recursively freeze it before freezing the parent object. Since each object is processed once, the total runtime is linear O(n).
What is the best approach for Make Object Immutable?
The recursive deep-freeze approach is the most reliable method. Traverse the object using DFS, recursively freeze nested objects or arrays, then call Object.freeze on the current object. This ensures the entire structure becomes immutable. The algorithm runs in O(n) time where n is the number of nested objects and properties.
Is Make Object Immutable asked at Google/Amazon/Meta?
Problems involving immutability and object manipulation frequently appear in JavaScript-heavy interviews at companies like Meta and frontend-focused roles at Google or Amazon. They test understanding of Object.freeze, recursion, and nested data structures.
What data structure is used in Make Object Immutable?
The solution primarily operates on JavaScript objects and arrays. Conceptually, the structure behaves like a tree where nested objects are child nodes, making depth-first traversal the natural strategy for applying deep immutability.
What is the time complexity of Make Object Immutable?
The optimal deep-freeze solution runs in O(n) time because each object or array in the structure is visited exactly once. Space complexity is O(h) due to the recursion stack, where h represents the maximum nesting depth of the object.

Ready to solve this problem?

Practice Make Object Immutable with our built-in code editor and test cases.

Practice on FleetCode