# Difference Between Mutable and Immutable Objects in JavaScript: A Complete Guide

> Understand the core difference between mutable and immutable objects in JavaScript. Learn how object state changes and explore practical examples to solidify your understanding.

- Repository: [H5BP/Front-end-Developer-Interview-Questions](https://github.com/h5bp/Front-end-Developer-Interview-Questions)
- Tags: deep-dive
- Published: 2026-03-05

---

**Mutable objects in JavaScript allow their internal state to be changed after creation, while immutable objects cannot be altered once defined.**

The distinction between mutable and immutable objects is a fundamental concept in JavaScript that directly impacts how you manage state, memory, and side effects in applications. According to the h5bp/Front-end-Developer-Interview-Questions repository, this topic appears as a core interview question in [`src/questions/javascript-questions.md`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/src/questions/javascript-questions.md) (lines 36-38), testing candidates' understanding of JavaScript's type system. Grasping the difference between mutable and immutable objects enables developers to write more predictable code and avoid common bugs related to unintended reference sharing.

## Understanding Mutable Objects in JavaScript

Mutable objects are reference types that permit modifications to their properties or elements after instantiation. When you alter a mutable object, you change the underlying data at the same memory address, which affects all references to that object throughout your codebase.

### Common Mutable Types and Mutation Risks

Most built-in object types in JavaScript are mutable by default:

- Plain objects (`{}`)
- Arrays (`[]`)
- `Date` objects
- Custom class instances

This mutability creates risks when the same reference is shared across different parts of an application. Changes made in one location propagate to all other references, potentially causing difficult-to-track side effects.

```javascript
// Mutable object example
const mutable = { name: "Alice", age: 30 };
mutable.age = 31;          // Directly mutates the same object
console.log(mutable);      // { name: "Alice", age: 31 }

```

In this example from the repository's documentation, modifying the `age` property changes the original object instance rather than creating a new one.

## Understanding Immutable Objects in JavaScript

Immutable objects cannot be modified after creation. Instead of altering existing data, operations on immutable values return new instances, ensuring the original remains unchanged.

### Primitive Values and Natural Immutability

All primitive values in JavaScript are immutable by design:

- `Number`
- `String`
- `Boolean`
- `null`
- `undefined`
- `Symbol`
- `BigInt`

Attempting to modify a primitive value throws a `TypeError` or silently fails, depending on the operation and mode.

```javascript
// Immutable primitive example
const immutable = "Hello";
// immutable[0] = "h";      // TypeError – strings cannot be altered
// Instead, create a new string:
const newImmutable = immutable.replace("H", "h");
console.log(newImmutable); // "hello"

```

### Enforcing Object Immutability with Object.freeze

While plain objects are mutable by default, JavaScript provides `Object.freeze()` to create immutable structures. This method prevents extensions and makes existing properties non-writable.

```javascript
// Immutable object via Object.freeze
const frozen = Object.freeze({ id: 1, status: "new" });
frozen.status = "done";    // Fails silently in non-strict mode (or throws in strict mode)
console.log(frozen);       // { id: 1, status: "new" }

```

For deep immutability, third-party libraries like **Immutable.js** provide persistent data structures that ensure any modification returns a new object rather than mutating the original.

## Practical Patterns for Immutability

Modern JavaScript development favors immutable patterns even with mutable types, particularly in frameworks like React that rely on change detection for rendering optimization.

### Creating New Objects Instead of Mutating

The spread operator and `Object.assign()` enable shallow copying with property overrides, preserving the original reference:

```javascript
// Creating a new object instead of mutating (common immutable pattern)
const original = { a: 1, b: 2 };
const updated = { ...original, b: 3 }; // shallow copy with changed property
console.log(original); // { a: 1, b: 2 }
console.log(updated);  // { a: 1, b: 3 }

```

This approach ensures the `original` object remains unchanged while producing a new `updated` instance with the desired modifications.

## Performance Characteristics and Trade-offs

Immutability offers significant architectural benefits but introduces computational costs. Understanding these trade-offs helps determine when to enforce strict immutability versus allowing controlled mutations.

**Benefits of immutability include:**

- **Predictable state management** – Eliminates side effects from shared references
- **Safer concurrent updates** – Prevents race conditions in asynchronous operations
- **Efficient change detection** – Enables React's reconciliation algorithm to compare references rather than deep equality

**Costs of immutability include:**

- **Increased memory usage** – Each operation creates new objects rather than reusing existing memory
- **Additional boilerplate** – Requires explicit copying patterns or library dependencies like Immutable.js

## Summary

- **Mutable objects** (plain objects, arrays, `Date`) allow in-place modifications that affect all references to the same instance, risking side effects across your codebase.
- **Immutable primitives** (`String`, `Number`, `Boolean`, `Symbol`, `BigInt`, `null`, `undefined`) cannot be altered after creation and require new instances for modifications.
- **`Object.freeze()`** provides runtime enforcement of immutability for objects, though it only affects top-level properties (shallow freeze).
- **Immutable patterns** using the spread operator or libraries like Immutable.js create new objects rather than mutating originals, supporting predictable state management in React and other frameworks.
- The h5bp/Front-end-Developer-Interview-Questions repository identifies this distinction as a critical interview topic in [`src/questions/javascript-questions.md`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/src/questions/javascript-questions.md) (lines 36-38).

## Frequently Asked Questions

### What is the main difference between mutable and immutable objects in JavaScript?

Mutable objects allow their internal state to be changed after creation, meaning modifications affect the original memory reference. Immutable objects cannot be altered once defined; any operation that appears to modify them actually returns a new instance while leaving the original unchanged.

### Are JavaScript primitives immutable?

Yes, all primitive values in JavaScript—`Number`, `String`, `Boolean`, `null`, `undefined`, `Symbol`, and `BigInt`—are immutable by nature. You cannot change the contents of a string or number directly; you must create a new value with the desired changes.

### How do you make objects immutable in JavaScript?

You can use `Object.freeze()` to prevent modifications to an object's existing properties and prevent new properties from being added. For deep immutability or complex data structures, use libraries like Immutable.js, which provide persistent data structures that always return new instances on modification rather than mutating existing objects.

### Why does React recommend immutability?

React relies on reference equality to determine when components need re-rendering. Immutable objects make change detection efficient because you can compare object references with `===` rather than performing expensive deep equality checks. Immutability also prevents accidental side effects where child components modify shared state without the parent component's knowledge.