Hone logo
Hone
Problems

Deep Freeze Implementation in JavaScript

Deep freezing in JavaScript is a technique to prevent any modifications to an object and its nested objects, including property additions, deletions, and value changes. This is incredibly useful for creating immutable data structures, ensuring data integrity in complex applications, and preventing accidental or malicious modifications to critical objects. Your task is to implement a function that performs a deep freeze on a given JavaScript object.

Problem Description

You need to implement a function called deepFreeze(obj) that recursively freezes an object and all its nested objects, preventing any future modifications. "Freezing" means that the object's properties cannot be added, deleted, or modified. This includes preventing changes to primitive values stored as properties and preventing modifications to nested objects.

Key Requirements:

  • Recursion: The function must recursively traverse the object and its nested objects.
  • Property Freezing: Each property of the object, including properties of nested objects, must be frozen.
  • Prevent Property Addition/Deletion: After freezing, it should be impossible to add or delete properties from the object or its nested objects.
  • Prevent Value Modification: It should be impossible to modify the values of existing properties (primitive or object).

Expected Behavior:

After calling deepFreeze(obj), any attempt to modify the object or its nested objects (e.g., assigning a new value to a property, adding a new property, deleting a property) should throw a TypeError.

Edge Cases to Consider:

  • Null or Undefined Input: The function should handle null or undefined input gracefully (e.g., return the input unchanged or throw an error – specify your choice in the Notes section).
  • Non-Object Input: The function should handle non-object inputs (e.g., numbers, strings, booleans) gracefully. Freezing these types is not meaningful, so you can either return them unchanged or throw an error.
  • Circular References: The function should avoid infinite loops when encountering circular references (objects referencing themselves directly or indirectly). A simple check for already frozen objects can prevent this.
  • Prototype Properties: The function should not freeze properties defined on the object's prototype chain. It should only freeze the object itself and its direct properties.

Examples

Example 1:

Input: { a: 1, b: { c: 2, d: 3 } }
Output: { a: 1, b: { c: 2, d: 3 } } (after deepFreeze)
Explanation: The input object and its nested object 'b' are frozen.  Attempting to modify any property (e.g., obj.a = 4, obj.b.c = 5, obj.newProp = 6, delete obj.a) will throw a TypeError.

Example 2:

Input: null
Output: null
Explanation:  Handles null input gracefully by returning it unchanged.

Example 3:

Input: { a: 1, b: { c: 2, d: { e: 4, f: [5,6] } } }
Output: { a: 1, b: { c: 2, d: { e: 4, f: [5,6] } } } (after deepFreeze)
Explanation:  Demonstrates deep freezing of nested objects and arrays within objects.  Modifying any of these values or structures will result in a TypeError.

Constraints

  • The function must be implemented in JavaScript.
  • The function should be reasonably efficient. While performance is not the primary concern, avoid unnecessary overhead.
  • The function should not modify the original object unless it is being frozen.
  • The function should not freeze properties on the prototype chain.
  • The function should handle circular references without causing infinite loops.

Notes

  • Consider using Object.isFrozen() to check if an object is already frozen to prevent infinite loops with circular references.
  • You can use Object.defineProperty() to freeze properties. Pay close attention to the configurable and writable attributes.
  • Decide how you want to handle null or undefined input and non-object inputs. Document your choice in a comment at the beginning of your function.
  • The goal is to create a robust and reliable deep freeze implementation. Test your code thoroughly with various scenarios, including nested objects, arrays, circular references, and edge cases.
Loading editor...
javascript