A mutable object can be changed in place; an immutable one cannot, so every “change” builds a new object. This matters because names (variables) point at objects: if two names point at one mutable object, a change through one name is visible through the other.

Which is which

MutableImmutable
Pythonlist, dict, set, most class instancesint, float, str, tuple, frozenset, bytes, None
JavaScriptobjects, arrays, Map, Setprimitives: numbers, strings, booleans, null, undefined, bigint, symbol

In JavaScript, const only stops rebinding the name; a const array can still be pushed to. Object.freeze makes an object shallowly immutable.

Example

a = [1, 2]; b = a; b.append(3); print(a)    # [1, 2, 3]  same list, mutated
s = "hi";  t = s; t += "!";     print(s)    # hi         str is immutable: t now points at a new string
const arr = [1, 2];
arr.push(3);            // allowed: mutation
console.log(arr);       // [ 1, 2, 3 ]
// arr = [];            // TypeError: Assignment to constant variable (rebinding)
  • Safe to share between functions and threads: nobody can change it under you.
  • Can be a hash map key (it must stay hashable).
  • React state relies on it: you replace objects instead of mutating them, so a cheap === check spots changes.

#2 · Python's object model, shallow-vs-deep-copy.

Check yourself

Leads to

  • Shallow vs deep copy: A shallow copy makes a new outer container that holds the same inner objects; a deep copy copies everything all the way down.