Photo by Erol Ahmed on Unsplash
What's the big difference between passing Arguments by Reference vs Passing Arguments by Value?
Primitive Values
In JavaScript, as with many other languages, at some point, you'll come across this concept. Going back to the call stack and the heap, and where data is stored, Primitives (Number
, String
, Boolean
, Undefined
, Null
, Symbol
, BigInt
) are stored in the call stack. Objects (Object Literal
, Arrays
, Functions
, more...), are stored in the heap.
When we create a primitive value, JavaScript creates a unique identifier with the value name. It then allocates the memory to an address, with a value. The identifier points to the address, but not the value itself. Primitive values, are immutable. Meaning, even if we might reassign a value, or alter it somewhere else, it does not change everywhere else that the value exists.
let season = "Fall";
let nextSeason = season;
season = "Winter";
console.log(season);
console.log(nextSeason);
//// Returns
// Winter
// Fall
Even though season
was reassigned to a value of Winter
, when we mutate it, it does not change the fact that nextSeason
was initially set to Fall
. It remains unchanged.
Reference Values
When we create a new object, it's stored in the heap, as the memory address, and then the value itself. When we declare a variable as an object, the identifier created for it, points to a piece of memory in the stack, which in turn points to a piece of memory in the heap where the object is stored.
Because of this, if multiple copies are created of an object, every time that happens, a new object is not created in memory. It just points to the same identifier for the original object. And so mutating one object has the effect that it changes all objects that point to that same memory address.
const dog = {
name: "Beau",
age: 15
};
const puppy = dog;
puppy.age = "10 months";
console.log('Puppy:', puppy)
// Returns
// Puppy: {name: 'Beau', age: '10 months'}
console.log('Dog:', dog)
// Returns
// Dog: {name: 'Beau', age: '10 months'}
It's important to understand the difference between Primitives vs Objects, because otherwise it can lead to some pretty nasty surprises, and bugs in our code. Also, so that when moving into functions, it's possible to understand the difference between Passing by Reference vs. Passing by Value.
Passing By Value
Moving into Functions, if we pass a primitive value into a function as an argument, even if a function manipulates that value inside of the context of the function, outside of the function itself, the value will remain as it was.
Ex:
let x = 1;
function alter(arg) {
arg = 100;
return arg;
};
change(x)
// Returns 100
console.log(x)
// returns 1
Passing by Reference
When we pass a reference type to the function, what's copied is the reference object to the memory heap. Both point to the same object in memory. When an object is manipulated in a function, it's the same as manipulating the object itself, as both references point to the same object. Change in one place, and everywhere else, the object has been altered.
const dog = {
name: "Beau",
age: 15
};
const happyBirthday = function(arg){
arg.age = arg.age + 1;
}
happyBirthday(dog)
console.log(dog)
// Returns
dog {name: 'Beau', age: 16}
Conclusion
To sum it, when a primitive type is passed into a function, it creates a copy. When we pass an object into a function, it's the same as passing the object itself. Which is something that we should be careful with, as it can again, lead to large issues.
Top comments (0)