Demystifying pass by value and pass by reference in JavaScript once and for all

Jainishshah
4 min readFeb 12, 2021

When I pass something to a function will it be passed by value or passed by reference? You would definitely have stumbled upon this concept no matter which programming language you use. If you come from C/C++ background like me you know that you have the choice in your hand. To pass by reference you’ll accept the argument as a pointer else as a primitive value like

int function abc(int a){} => pass by value 
OR
int function abc(int *a){} => pass by reference

In short, if you want your called fn to manipulate the value, you pass a reference (pointer) else you send a copy of the value.

But that is in C/C++ ( P.S: best languages ever), now we are in JavaScript env. You don’t have the capability to explicitly send something as a reference and there is no concept of the pointer so how do you do determine what’s going on?

Don’t freak out, I am here for the rescue. And I’ll make a bold statement here “Every argument passed in JavaScript is passed by value” i.e a copy of that variable is passed. Let’s take an example here

function doSomething(x){
x = x*x;
console.log(x)
}
var y = 10;
doSomething(y); // 100
console.log(y); // 10

OK so when is called doSomething() with y, the copy of that value was passed and assigned to a and so the output was 100 while the value of y still remained 10.

But here I give you the chance to prove me wrong. Take a look

function doSomething(argObj){
argObj.value = "shah";
}
var obj = {
name: 'jainish'
};
console.log(obj.name); // jainish
doSomething(obj);
console.log(obj.name); //shah

Well… well… well… I’ll give you a moment to cheer. You have the perfect argument to counter me. “Hey Jainish, if everything is sent as a copy why did my actual object change its value ? You are such a fool to make a bold statement like that, stop writing shit you don’t fully understand” (Well I assume the hate here will be similar to Twitter, don’t judge me ).

Guess what I still stand by my statement. But if I still say I am right and you are also right, who’s actually right then ??? Well, we both are!!!

The answer lies in how JS works under the hood. You see there are two types of values in JS. Primitives and non-primitives. The primitives are [Number, Symbol, String, Boolean, BigInt, Undefined] and non-primitive is [Object] (Let’s keep Null, Function, NaN, etc out for a minute for sake of simplicity).

The values of primitive are fixed (eg Number is in the range -(2⁵³ − 1) and 2⁵³ − 1)). So when the code is being executed these values are actually stored in the “stack”. While non-primitives like Object (Arrays, Maps, Sets too, but they are derived from Object only) don’t have a fixed length so they are stored in “heap”. The variable that holds the primitives has the “value” stored in them while the variable that holds non-primitives have “reference” to the memory in the heap.

var x = 6 ; ======> x[6] (memory block actually hold the value 6)
var z = {name:'jainish'} ==> z[refToHeap]==>heap[ {name:'jainish'} ]
(variable z have the value of the memory location)

Ok now coming to my statement, when you call a function the JS engine compiles the code and then copies the value accordingly. So in the case of primitive, it copies the value itself and in the case of Obj, it copies the reference.

function abc(x){
x = x*x;
console.log(x);
}
var y = 6;
abc(6);

The value 6 is copied in a new memory location defined by variable “x”

function abc(argObj){
argObj.name = "shah";
}
var obj = {name: 'jainish'};
console.log(obj.name);
abc(obj);
console.log(obj.name);

the function copies the reference (value) of the Obj to argObj (So it’s still “pass by value”). But since manipulation to this value affects the reference, the changes will be reflected in both Obj and argObj. And since we are copying a reference here it’s referred to as “pass by reference”.

How to avoid this => Simple pass a different memory location (how ? easy peasy in ES6+ you can you Object destructuring [{…Obj}] ). Else you can assign argObj to different memory location like

function abc(argObj){
argObj = {
name: 'shah'
};
}
var obj = {name : 'jainish'};
console.log(obj.name); // jainish
abc(obj);
console.log(obj.name); // jainish
abc({...obj});console.log(obj.name) // jainish;// In destructuring a new Obj is created so the reference will
// always be different. In this case you are not even using the
// reference of obj when you call the function abc

We are finally done here. It was a long one but hey if it helped you I am very happy. Ok, I’ll take one more example and I want you to figure it out yourself. It’s on a different topic but if you find the answer do add a response to this article.

function doSomething(){ 
for(var i=0;i<10;i++){
setTimeout( function(){ console.log(i) }, i*1000);
}
}

For further queries feel free to reach out at jainishshah12@gmail.com

--

--