The difference between shallow freeze and deep freeze lies in how the freezing behavior is applied to nested objects. Here’s a breakdown of the two concepts:
1. Shallow Freeze
- Definition: Freezes only the top-level properties of an object.
- Behavior:
- Prevents adding, removing, or modifying the top-level properties.
- Does not freeze nested objects; they remain mutable.
- Example:
const shallowObject = { name: "Alice", details: { age: 25, city: "New York" }, }; Object.freeze(shallowObject); // Top-level properties are immutable shallowObject.name = "Bob"; // Ignored shallowObject.newProp = "test"; // Ignored // Nested objects are still mutable shallowObject.details.age = 30; // Allowed console.log(shallowObject); // Output: { name: "Alice", details: { age: 30, city: "New York" } } 2. Deep Freeze
- Definition: Freezes the object along with all its nested objects and arrays, recursively.
- Behavior:
- Ensures that no part of the object (top-level or nested) can be modified.
- Example:
const deepObject = { name: "Alice", details: { age: 25, city: "New York" }, }; // Deep freeze function function deepFreeze(object) { const propertyNames = Object.getOwnPropertyNames(object); for (const name of propertyNames) { const value = object[name]; if (value && typeof value === 'object') { deepFreeze(value); // Recursively freeze } } return Object.freeze(object); } deepFreeze(deepObject); // Neither top-level nor nested properties can be changed deepObject.name = "Bob"; // Ignored deepObject.details.age = 30; // Ignored console.log(deepObject); // Output: { name: "Alice", details: { age: 25, city: "New York" } } Comparison Table
| Feature | Shallow Freeze | Deep Freeze |
|---|---|---|
| Scope | Only freezes top-level properties. | Freezes top-level and nested objects. |
| Nested Object Mutability | Mutable. | Immutable. |
| Implementation | Object.freeze(object). | Custom recursive function with Object.freeze(). |
| Example Mutation | Modifications to nested objects are allowed. | No modifications allowed at any level. |
Use Cases
-
Shallow Freeze:
- Suitable when only the top-level properties need to be immutable.
- Examples: Configurations where nested properties are managed independently.
-
Deep Freeze:
- Ideal when complete immutability is required for the entire object hierarchy.
- Examples: Ensuring data consistency for deeply nested objects in state management.
Considerations
- Performance:
- Deep freezing can be computationally expensive for large or deeply nested objects.
- Cyclic References:
- If the object contains circular references, you'll need to track visited objects to avoid infinite recursion.
Handling Cyclic References
To handle cyclic references, you can maintain a WeakSet of visited objects:
function deepFreeze(object, visited = new WeakSet()) { // If the object is already visited, return it if (visited.has(object)) return object; // Add the object to the visited set visited.add(object); // Retrieve property names const propertyNames = Object.getOwnPropertyNames(object); // Freeze each property for (const name of propertyNames) { const value = object[name]; if (value && typeof value === 'object') { deepFreeze(value, visited); } } return Object.freeze(object); } This prevents infinite recursion for cyclic references.
Top comments (0)