Progress pill
Intermediate JavaScript

Value vs Reference

  • Pass by value
  • Pass by reference
JavaScript treats different kinds of values in different ways.
Some values are copied when you assign them to a variable.
Others are shared when you assign them to a new variable, so if you change one, the other one changes too.

Pass by value

When a value is passed by value, JavaScript makes a copy of it.
So if you change one, it doesn’t affect the other.
This happens with primitive types, like:
  • numbers
  • strings
  • booleans (true and false)
  • null
  • undefined
Let’s look at an example:
let a = 5 let b = a b = 10 console.log(a) // 5 console.log(b) // 10
We gave b the value of a, but then we changed b to 10.
Since numbers are passed by value, JavaScript copied the 5 into b. The 5 in b is independent from the original 5 in a so changing the value of b had no effect on a.
Let’s try with a string:
let name1 = "Alice" let name2 = name1 name2 = "Bob" console.log(name1) // Alice console.log(name2) // Bob
Again, changing name2 didn’t affect name1, because strings are also passed by value.
The same thing happens when you pass a primitive to a function: it gets copied. So the function can’t change the original.
function plusOne(x) { x = x + 1 } let number = 5 plusOne(number) console.log(number) // 5
Even though inside the function 1 was added to x, the original number didn’t change.
That’s because only a copy was passed into the function.

Pass by reference

Objects are passed by reference.
That means instead of copying them, JavaScript just passes a reference to it, and if you modify it, all other variables that point to it will see the change too.
For example:
const person1 = { name: "Alice" } const person2 = person1 person2.name = "Bob" console.log(person1.name) // Bob console.log(person2.name) // Bob
Both person1 and person2 point to the same object in memory.
So when we changed person2.name, we also changed person1.name, because they’re both looking at the same thing.
Arrays are objects, so let’s try the same with an array:
const list1 = [1, 2, 3] const list2 = list1 list2.push(4) console.log(list1) // [1, 2, 3, 4] console.log(list2) // [1, 2, 3, 4]
We pushed 4 into list2, but list1 was affected too, because they both refer to the same array.
Let’s see what happens when we pass an object to a function:
function rename(user) { user.name = "Charlie" } const person = { name: "Dana" } rename(person) console.log(person.name) // Charlie
The function changed the object! That’s because it received a reference to the original person object.
It didn’t get a copy. It got access to the original object, and with that it got the ability to modify it.
It's important to remember this distinction, because otherwise our code might behave differently from what we expect. For example, we might write a function with the expectation that it will not modify the arguments it receives, and find out later that it was actually modifying them (because they were objects, so they were passed by reference).