Mutability & References
The problem
When two names can refer to the same underlying data, changing the data through one name silently changes what the other name sees — a frequent source of bugs unless you understand exactly when values are copied versus shared.
Why now
Variables and state establish that a name is bound to a value, but not whether that binding is a private copy or a shared pointer to the same data. Once arrays and lists introduce values large enough that copying them is expensive, languages start passing references instead — and functions-and-relations already showed that two names mapping to the same object is just a non-injective relation, not a special case.
Mental model
A primitive value (number, boolean) is copied on assignment — two names, two independent boxes. An object or array is instead a label pointing at a box elsewhere — assignment copies the pointer, not the box, so two names can point at the same mutable box. Every 'I changed one and the other one changed too' bug is exactly this.
Requires
- Variables & StateProgramming Fundamentals
Reference semantics is a refinement of what 'assignment' does to a variable's binding; you need the variable/binding concept before distinguishing copy-by-value from copy-by-reference.
- Functions & RelationsMathematical Thinking
Aliasing — two names pointing at the same object — is precisely a non-injective relation between names and memory locations; seeing it that way explains why aliasing is a normal, not exceptional, case.
Helps
- Arrays & ListsProgramming Fundamentals
Reference semantics matters most in practice once values are large collections (arrays, objects) that are expensive to copy — the motivation is clearest with that context, though not strictly required.
Unlocks
Related
Used in
- Pass-by-value vs. pass-by-reference semantics across languages (C, Java, Python, JavaScript)
- React's rule against mutating state directly (relies on reference equality for re-render checks)
- Deep vs. shallow copy utilities (structuredClone, JSON parse/stringify tricks)
- Shared mutable state bugs in concurrent/multi-threaded systems
Projects
- Write a function that mutates an array argument and one that returns a new array instead; demonstrate the difference on the caller's original data
- Implement a deep-clone function for nested objects/arrays without using a library, handling the aliasing correctly
Examples
- let a = [1,2]; let b = a; b.push(3); — a is now [1,2,3] too, because a and b reference the same array
- React's setState([...oldArray, newItem]) creates a new reference specifically to avoid this aliasing trap
Resources
Mastery checklist
- I can predict whether an assignment copies a value or shares a reference for a given type
- I can explain an aliasing bug in terms of two names mapping to the same object
- I can write a function that avoids mutating its arguments when that's the desired contract
- I can implement a correct deep copy of a nested structure