DEV Community

Cover image for Pass By Reference Vs Pass By Value
Yohanes Setiawan
Yohanes Setiawan

Posted on

Pass By Reference Vs Pass By Value

Hi Devs! Today we will discuss one of the most fundamental concept in Javascript "Pass by Value" and "Pass by Reference". This concept is so important, even this question is often pop up in job interview. Why is that? By understanding how this works, it will help us to be a better programmer that can understand the flow of data in the application.

Before we can dive in into the explanation. We must know that, in Javascript data types are classified into two categories: primitive and non-primitive.

Here is a list primitive data types in Javascript:

  • string -- an array of character

  • number -- integer, floats, etc...

  • bigint -- in case you need integer values larger than the range supported by the Number

  • boolean -- true or false

  • null -- empty value

  • symbols -- an unique value or often used as unique identifier that is not equal to any other value

  • undefined -- declared variable but the value is still not assigned.

Meanwhile all objects, arrays, and functions fall under the category of non-primitive data types.

Okay, we got this. Let's jump into the explanation!

Pass by Reference

Let's take a look at the code below to understand what is pass by reference is

let john = {
  name: 'John Doe',
  gender: 'male',
  score: 95
};

let JohnDupe = john;
console.log(JohnDupe); // {name: 'John Doe', gender: 'male', score: 95}
console.log(john); // {name: 'John Doe', gender: 'male', score: 95}
Enter fullscreen mode Exit fullscreen mode

Okay, we have create a new variable JohnDupe and assign the value from John. What happen next if we modify the score of JohnDupe?

johnDupe.score = 50;

console.log(JohnDupe); // {name: 'John Doe', gender: 'male', score: 50}
console.log(john); // {name: 'John Doe', gender: 'male', score: 50}
Enter fullscreen mode Exit fullscreen mode

Notice that the value score of John is also changed! What actually happened? When we create John (new object), we are store the value in the memory within some address. And when we assign the value from John to johnDupe, actually instead of creating a copy of John, JohnDupe value is referencing the value (the address) of John in the memory.

To fix the problem above, we need to actually create a copy of John and assign it to a new variable and then we can change the score without affecting the original John.

let john = {
  name: 'John Doe',
  gender: 'male',
  score: 95
};

let anotherJohn = {...john}

anotherJohn.score = 50;

console.log(john); // {name: 'John Doe', gender: 'male', score: 95}
console.log(anotherJohn); // {name: 'John Doe', gender: 'male', score: 50}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have copied john using spread operator and then assign it into anotherJohn. By creating new object, anotherJohn actually store the copied object in the memory with different address from john. anotherJohn is not referencing john anymore like before, they are completely a different entities. To prove that, take a look at the code below

let person = {
  name: 'Nicola Tesla',
  gender: 'male',
};

let personDupe = person;

let anotherPerson = {
  name: 'Nicola Tesla',
  gender: 'male',
};

console.log(person === personDupe); // true
console.log(person === anotherPerson); // false
Enter fullscreen mode Exit fullscreen mode

In the example above, we tried to compare equal person === personDupe which will be print true because personDupe is pointing the address from person. However when we tried to compare equal person === anotherPerson this will be print false because they are not the same object even if they are have the same properties and values.

This behavior is also same with Array.

let fruits = ['apple ๐ŸŽ', 'strawberry ๐Ÿ“', 'banana ๐ŸŒ'];

let fruitsDupe = fruits;

let anotherFruits = ['apple ๐ŸŽ', 'strawberry ๐Ÿ“', 'banana ๐ŸŒ'];

console.log(fruits === fruitsDupe); // true
console.log(fruits === anotherFruits); // false
Enter fullscreen mode Exit fullscreen mode

I have an analogy for having us easier to understanding "pass by reference" by assuming it as a google sheet / google docs.

Let's say a group of student is given an assignment by a teacher to put their own opinion about global warming. ๐ŸŒŽ The teacher want the format of the assignment to be in a single file.

John as the class president take the initiative to create a google docs so the student could collaborate easily. John then share the link with his classmates. Mary is the first student that make a change into the docs and add a bunch of paragraph of her idea about global warming. Later that night Suzie opened the google docs and add her own opinion, followed by Andy and so on. Finally after all the student is finished add their own opinion, John shared the google docs to the teacher. All is good and the class got an "A" for the assignment โœจ

From the case above, no matter how many times google docs is modified by students in the end it still be only modifiying one file (master file).

So far so good! We are know what is exactly pass by reference is. โœจ

Pass by Value

If you are already understanding pass by reference, you already understanding pass by value is. Primitive values such as numbers or strings will actually create a copy.

const num = 10

function passByValue(val) {
  return val += 1
}


console.log('[passByValue]:', passByValue(num)) // [passByValue]: 11
console.log('[num]:', num) // [num:] 10
Enter fullscreen mode Exit fullscreen mode

In the code above, we create a variable num with the value of 10. Also we create a function passByValue which take a value as parameter and add it by 1. If we were trying to run the code above, passByValue will return 11, however num variable is still 10. the original value of num is not changed at all.


I hope this short article will help you to understanding the concept of pass by reference and pass by value. The main difference between pass by value and pass by reference is, pass by value will create a new space in memory and make a copy of a value. Pass by reference however instead of making a copy, the value stored in memory gets referenced.

Top comments (7)

Collapse
 
smlka profile image
Andrey Smolko

Damn, this is so brilliant comment!!!
Exactly, there are just NOT any ways to mutate primitive data type value:

let obj = {}
let obj_c = obj
let str = ''
let str_c = str
// mutate value in obj
obj[0] = 1
obj_c // {0: 1}
// try mutate value in str
str[0] = 1 // or try to mutate value in str in your own manner
str // ''
str_c // ''
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ

You missed bigint on the primitives list

Collapse
 
yohanesss profile image
Yohanes Setiawan

Thanks Jon, added! I rarely use it, so I think I missed it ๐Ÿ˜…

Collapse
 
yohanesss profile image
Yohanes Setiawan

Wow, I might will check it out. Thank you!

Collapse
 
ecyrbe profile image
ecyrbe • Edited

Maybe you made a typo error because in Javascript everything is passed as Reference, not Value.

Proof :

const object = { hello: 'world' };
function mutate(obj) {
  obj.test = 'test';
}
mutate(object);
console.log(object); // { hello: "world", test: "test" }
Enter fullscreen mode Exit fullscreen mode

If it where by value, object would not have changed.

Collapse
 
cicirello profile image
Vincent A. Cicirello

It is still pass by value. In this case, the value passed for obj is a reference to an object, which is why the state of the object passed for obj can change. However, if you tried to do something like obj = someOtherObject inside of that function, the change is only observable inside of that function. If it was pass by reference, that change would also be observable by the caller. But it is not.

 
ecyrbe profile image
ecyrbe

Oh, yeas, my bad.

Objects are references is the right explaination. At first you wrote : "Now objects are mutable and hold references to values" witch i interpreted as "Now Objects are mutable and properties hold references to values" which my example disproved.

But yes, One single Object is by itself stored as a reference to the actual object.
Proof

let test = { hello: "world" };
const test2 = test;
test.test = "test";
console.log(test2); // { hello: "world", test: "test" }
Enter fullscreen mode Exit fullscreen mode