Reference vs Value
One of the most important concepts to understand in JavaScript is how variables store data in your computer's memory. There are two main categories of data types: value types (primitives) and reference types (objects, arrays, functions).
⚠️ WARNING: This is a tricky topic, so take your time to understand it fully!
How Value Types Work
When you assign primitive values, JavaScript copies the actual value directly into your computer's memory:
const a = 10
const b = "hi"
| Variable | Value |
|---|---|
a |
10 |
b |
"hi" |
Copying Value Types
When you copy a variable that holds a primitive value, JavaScript creates a completely new copy of that value in memory:
let a = 10
let b = a // Copies the VALUE of a
b = b + 1 // Only changes b, not a
| Variable | Value |
|---|---|
a |
10 |
b |
11 |
How Reference Types Work
When you create arrays or objects, JavaScript stores a reference (memory address) to where the data lives:
const c = [1, 2]
| Variable | Value (Reference) |
|---|---|
c |
0x001 |
| Memory Location | Actual Data |
|---|---|
0x001 |
[1, 2] |
Think of 0x001 as a "hotel room number" - the variable stores the room number, not the actual contents of the room.
Copying Reference Types
When you copy a variable that holds an array or object, JavaScript copies the reference (memory address), not the actual data:
const c = [1, 2]
const d = c // Copies the REFERENCE, not the array
d.push(3) // Modifies the array that both c and d point to
| Variable | Value (Reference) |
|---|---|
c |
0x001 |
d |
0x001 |
| Memory Location | Actual Data |
|---|---|
0x001 |
[1, 2, 3] |
Both c and d store the same memory address (0x001), so they both point to the same array in memory.
Creating New References
When you create a new array/object, JavaScript allocates a new memory location:
let c = [1, 2] // Memory location 0x001
let d = [3, 4, 5] // Memory location 0x002 (different!)
d.push(6)
| Variable | Value (Reference) |
|---|---|
c |
0x001 |
d |
0x002 |
| Memory Location | Actual Data |
|---|---|
0x001 |
[1, 2] |
0x002 |
[3, 4, 5, 6] |
Comparing References
Since JavaScript compares the Value (Reference) column and not the actual contents, two different arrays/objects with the same contents are considered different:
const a = [1, 2]
const b = [1, 2] // Same contents, but different memory locations!
console.log(a == b) // false
console.log(a === b) // false
| Variable | Value (Reference) |
|---|---|
a |
0x001 |
b |
0x002 |
| Memory Location | Actual Data |
|---|---|
0x001 |
[1, 2] |
0x002 |
[1, 2] |
JavaScript is asking: "Is 0x001 the same as 0x002?" The answer is no, even though the contents are identical.
When Equality Returns True
const a = [1, 2]
const b = a // Same reference!
console.log(a === b) // true ← Both point to same memory location
Objects Work the Same Way
let person1 = { name: "Kyle" }
let person2 = person1 // Same reference
person2.name = "Joe"
console.log(person1.name) // "Joe" ← Changed!
console.log(person2.name) // "Joe" ← Same object
console.log(person1 === person2) // true ← Same reference
// But creating a new object:
const person3 = { name: "Joe" }
console.log(person1 === person3) // false ← Different references
const with References
The const keyword prevents you from reassigning a variable, but it doesn't prevent you from modifying the contents of arrays/objects declared with const.
const only cares about the Value (Reference) column.
const arr = [1, 2]
// This works! We're not changing the reference
arr.push(3)
console.log(arr) // [1, 2, 3]
// This fails! We're trying to change the reference
arr = [4, 5, 6] // ❌ TypeError: Assignment to constant variable
| Variable | Value (Reference) |
|---|---|
a |
0x001 |
Functions and References
When you pass arrays/objects to functions, you're passing the reference which means the function can modify the original data:
function addElement(array, element) {
array.push(element) // Modifies the original array!
}
const numbers = [1, 2, 3]
addElement(numbers, 4)
console.log(numbers) // [1, 2, 3, 4] ← Original array modified