DEV Community

Mohamed Idris
Mohamed Idris

Posted on

"Mutable" vs "Immutable": Can You Change It After You Make It?

You copy an array to be "safe," tweak the copy, and somehow the original
changes too. You stare at the screen. You didn't touch the original. Did the
computer just lie to you?

Welcome to the world of mutable and immutable. Two words that explain a
ton of "wait, why did that change?" bugs.


The idea in one line

Mutable means "can be changed after it's made." Immutable means "locked
forever once it's made."


The metaphor: a whiteboard vs a printed photo

WHITEBOARD (mutable)            PRINTED PHOTO (immutable)
wipe it, rewrite it             can't edit it
same board, new content         want a change? print a NEW photo
Enter fullscreen mode Exit fullscreen mode

A whiteboard is mutable. You change what's on it, but it's still the same
board. A printed photo is immutable. You can't change it. If you want a
different picture, you make a brand new print and keep (or toss) the old one.


How it bites you in code

const original = [1, 2, 3]
const copy = original        // NOT a copy! both names point to the SAME array
copy.push(4)
console.log(original)        // [1, 2, 3, 4]  <- surprise! the original changed too
Enter fullscreen mode Exit fullscreen mode

copy = original did not make a new array. It just gave the same whiteboard
a second name. Writing through one name shows up under the other. Arrays and
objects in JavaScript are mutable, so this trap is everywhere.

// The fix: make a real new array (a fresh print), then change that
const original = [1, 2, 3]
const copy = [...original]   // new array with the same items
copy.push(4)
console.log(original)        // [1, 2, 3]  <- safe!
console.log(copy)            // [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

A real case: React state

React leans hard on immutability. If you change state in place, React often
can't tell anything changed, so your screen doesn't update.

// Wrong: mutating the same array. React may not re-render.
todos.push(newTodo)
setTodos(todos)

// Right: hand React a brand new array
setTodos([...todos, newTodo])
Enter fullscreen mode Exit fullscreen mode

The rule "don't mutate state, replace it" is this exact idea. Treat state like a
printed photo: make a new one instead of scribbling on the old.


Gotchas juniors hit

1. Thinking = copies.
For arrays and objects, = copies the reference (the name), not the contents.
Both names share one thing.

2. const does not mean immutable.
const arr = [1,2] just means you can't point arr at something else. You can
still arr.push(3). The box is locked; the contents are not.

3. Shallow copies only go one level deep.
[...arr] copies the top level. Nested objects inside are still shared. Deep
data needs deeper copying.


Recap

  • Mutable = changeable after creation (a whiteboard).
  • Immutable = locked after creation (a printed photo).
  • In JS, = shares the same thing; it does not copy it.
  • For safe updates (especially React state), make a new value instead of changing the old one.

Your turn

Run the const copy = original; copy.push(4) example yourself and watch the
original change. Then fix it with [...original]. Once that "aha" lands, explain
"whiteboard vs printed photo" to a friend.

Top comments (0)