Come with me now on a journey through code and data...

Pass By Value, Pass By Reference

I'm working my way through the points in this list of 33 fundamentals every JavaScript developer should know in order to make sure I understand the language thoroughly. This notebook is for working through code relating to point 3.

Exploring the effects of passing in values or references:

Make a function that alters a value but doesn't return it from the function.

Expectation: If passed a primitive / value then a new variable will be defined within the scope of the function and then thrown away. Our value won't change.

In [1]:
function mutate(value) {
    value = value.toUpperCase()
}
In [2]:
var value = 'apple'
In [3]:
mutate(value)
console.log(value)
apple

What about when we have an object / reference and pass a value from the object to the function?

In [4]:
var reference = {value: 'apple'}
In [5]:
mutate(reference.value)
console.log(reference.value)
apple

So when we use reference.value we're accessing the actual primitive in memory, not using or updating the reference.

Now to check how altering references work:

Expectation: If passed an object / reference then a new pointer will be assigned to the reference for the value property, the pointer will reference memory containing the new primitive we have set.

In [6]:
function mutateReference(reference) {
    reference.value = reference.value.toUpperCase()
}
In [7]:
mutateReference(reference)
console.log(reference.value)
APPLE

So without returning anything from the function, we've mutated the state of the object.

What about reassigning the object itself instead of accessing and changing it's properties:

In [8]:
function resetReference(reference) {
    reference = {}
}
In [9]:
resetReference(reference)
console.log(reference)
{ value: 'APPLE' }

reference hasn't been reset, changing the variable itself in this way will not work.

There's a difference between mutating objects (changing their property references) and reassigning objects (completely replacing the variable reference).

The object is reassigned within the scope of the function (like in the first example with a primitive) but it's not going to have any effect outside of the function.

Exploring effects of copied variables:

In [40]:
var value = 'apple'
var value_copy = value
var reference = {'value':'apple'}
var reference_copy = reference

Expectation: Changing value_copy won't have any effect on value as they're referencing different parts of memory. The primitive value has been completely copied when we created the new variable.

In [41]:
var value_copy = value_copy.toUpperCase()
In [42]:
console.log(`value: ${value}`)
console.log(`value_copy: ${value_copy}`)
value: apple
value_copy: APPLE

Fairly obvious as we've completely reassigned the value of value_copy

Expectation: Changing a property in reference_copy will change the property in reference since they're all just pointers in memory.

In [43]:
reference_copy.value = reference_copy.value.toUpperCase()
Out[43]:
'APPLE'
In [44]:
console.log(`reference.value: ${reference.value}`)
console.log(`reference_copy.value: ${reference_copy.value}`)
reference.value: APPLE
reference_copy.value: APPLE

Reassigning properties in the object means the same part of memory is updated, but reassigning the reference_copy variable itself will not affect the original reference:

In [45]:
reference_copy = {}
Out[45]:
{}
In [46]:
console.log(`reference.value: ${reference.value}`)
console.log(`reference_copy.value: ${reference_copy.value}`)
reference.value: APPLE
reference_copy.value: undefined