DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. Immutability in JavaScript: Patterns and Performance
XLinkedInReddit
MediumFrontend Engineering

Immutability in JavaScript: Patterns and Performance

D
DevPrep Team
February 10, 2026·2 min read·0
Table of Contents
  • Why Immutability?
  • Shallow vs Deep Copy
  • Object.freeze: Limited Protection
  • Immutable Update Patterns
  • Immer: Immutability Made Easy
  • Performance Considerations

Immutability prevents bugs, simplifies debugging, and enables powerful optimizations like React's reconciliation. Here's how to do it right.

Why Immutability?

// Mutable — bug-prone
const user = { name: "Rahul", scores: [90, 85] };
const copy = user;
copy.name = "Changed"; // Oops — user.name is also "Changed"!

// Immutable — safe
const user = { name: "Rahul", scores: [90, 85] };
const copy = { ...user, name: "Changed" }; // Original unchanged

Shallow vs Deep Copy

const original = { a: 1, nested: { b: 2 } };

// Shallow copy — nested objects are still shared!
const shallow = { ...original };
shallow.nested.b = 99; // original.nested.b is also 99!

// Deep copy
const deep = structuredClone(original); // Modern way
deep.nested.b = 99; // original.nested.b is still 2

Object.freeze: Limited Protection

const config = Object.freeze({
  api: "https://api.example.com",
  nested: { timeout: 5000 }
});

config.api = "changed"; // Silently fails (or throws in strict mode)
config.nested.timeout = 999; // WORKS! freeze is shallow!

// Deep freeze
function deepFreeze(obj) {
  Object.freeze(obj);
  Object.values(obj).forEach(v => {
    if (typeof v === "object" && v !== null) deepFreeze(v);
  });
  return obj;
}

Immutable Update Patterns

// Object
const updated = { ...state, name: "New Name" };

// Nested object
const updated = {
  ...state,
  address: { ...state.address, city: "Mumbai" }
};

// Array: add
const added = [...items, newItem];
// Array: remove
const removed = items.filter(i => i.id !== targetId);
// Array: update
const updated = items.map(i => i.id === targetId ? { ...i, done: true } : i);

Immer: Immutability Made Easy

import { produce } from "immer";

const nextState = produce(state, draft => {
  // Mutate the draft — Immer produces an immutable result
  draft.users[0].name = "Updated";
  draft.users.push({ name: "New User" });
  draft.settings.theme = "dark";
});
// state is unchanged, nextState has the updates

Performance Considerations

  • Spreading large objects is O(n) — avoid in hot loops
  • structuredClone is slow for large objects — only deep clone when necessary
  • Immer uses structural sharing — only changed paths create new references
  • React uses reference equality for re-render decisions — immutability enables this optimization

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • Why Immutability?
  • Shallow vs Deep Copy
  • Object.freeze: Limited Protection
  • Immutable Update Patterns
  • Immer: Immutability Made Easy
  • Performance Considerations

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.