Pass by value and pass by reference
Overview
This article does not explain pass-by-value and pass-by-reference with respect to other programming languages. It only explains pass-by-value and pass-by-reference with respect to JavaScript.
In JavaScript, when a function is called, the arguments can be passed in two ways:
Before understanding the pass-by-value and pass-by-reference, first, understand what primitive and non-primitive data types are.
Pass by value
Pass by value in JavaScript means that a copy of the actual parameter's value is made in memory i.e., a new memory allocation is done, and all the changes are made in that new value (i.e., copied value). The original value and the copied value are independent of each other as they both have a different space in memory i.e., on changing the value inside the function, the variable outside the function is not affected.
In simple language, we can understand it as, in a pass-by value, the function receives a copy of the variable, which is independent of the originally passed variable.
Pass by value in JavaScript requires more space as the functions get a copy of the actual content therefore, a new variable is created in the memory.
Let's see the below example:
function changeName(name) {
name = "rizwan";
}
let name = "Rizwan";
changeName(name);
console.log(name); // Rizwan
In the above example, we have created a function named changeName and passed the value of the variable name to it. Then, we have changed the value of the variable name to 'rizwan' inside the function. Now, we have console logged the value of the variable name outside the function. We got Rizwan in the console. This is because the value of the variable name is not changed inside the function. The value of the variable name is changed inside the function, but the variable name outside the function is not affected.
Same is the case if I declare a new variable, and pass the value of the variable name to it.
let num1 = 70;
let num2 = num1;
console.log(num1); // 70
console.log(num2); // 70
num1 = 40;
console.log(num1); // 40
console.log(num2); // 70
Here, we have assigned num1 a value of 70. This creates a space in memory by the name num1 and addresses 2001 (assumption). When we create a variable num2 and assign it the value of num1, then equals operator notices that we're dealing with a primitive values thus it creates a NEW SPACE in memory with address 2002 (assumption) and assigns it a copy of num1's value, i.e. 70. Now we can see that both the variables have different spaces in the memory, and both have a value of 70.
Now, if we change the value of num1, then num2 will have no effect as it has its own separate space in memory, and now it has nothing to do with the value of num2 as they both have different spaces (address) in memory.
Pass by reference
Unlike pass by value in JavaScript, pass by reference in JavaScript does not create a new space in the memory, instead, we pass the reference/address of the actual parameter, which means the function can access the original value of the variable. Thus, if we change the value of the variable inside the function, then the original value also gets changed.
It does not create a copy, instead, it works on the original variable, so all the changes made inside the function affect the original variable as well.
Let's see the below example:
function changeName(name) {
name.name = "rizwan";
}
let name = { name: "Rizwan" };
changeName(name);
console.log(name); // { name: 'rizwan' }
In the above example, we have created a function named changeName and passed the value of the variable name to it. Then, we have changed the value of the name property to 'rizwan' inside the function. Now, we have console logged the value of the variable name outside the function. We got { name: 'rizwan' } in the console. This is because the value of the variable name is changed inside the function. The value of the variable name is changed inside the function, and the variable name outside the function is also affected.
Now, let's see the same example with an array.
let originalArray = [1, 2, 3, 4, 5];
function changeArray(arr) {
arr.push(6);
}
changeArray(originalArray);
console.log(originalArray); // [1, 2, 3, 4, 5, 6]
In the above example, we have created a function named changeArray and passed the value of the variable originalArray to it. Then, we have pushed the value 6 to the array inside the function. Now, we have console logged the value of the variable originalArray outside the function. We got [1, 2, 3, 4, 5, 6] in the console. This is because the value of the variable originalArray is changed inside the function. The value of the variable originalArray is changed inside the function, and the variable originalArray outside the function is also affected.
Pass by reference vs pass by value
Pass by reference and pass by value are two different ways of passing the arguments to the function. In pass by value, a copy of the actual parameter's value is made in memory i.e., a new memory allocation is done, and all the changes are made in that new value (i.e., copied value). The original value and the copied value are independent of each other as they both have a different space in memory i.e., on changing the value inside the function, the variable outside the function is not affected.
Which one applies when?
You don't get to choose between pass by value and pass by reference in JavaScript — the type of the argument decides it. Primitives are always passed by value, and objects always pass a copy of the reference (this is often called call by sharing).
That last detail matters, because with objects, mutating and reassigning behave differently inside a function:
function update(user) {
user.name = "rizwan"; // mutation - changes the caller's object
user = { name: "someone else" }; // reassignment - only changes the local variable
}
const person = { name: "Rizwan" };
update(person);
console.log(person); // { name: 'rizwan' }
Mutating a property (user.name = "rizwan") follows the reference to the shared object, so the caller sees the change. Reassigning the parameter (user = ...) only points the local variable at a new object — the caller's variable still points at the original one. This is why JavaScript is not true pass by reference: the function receives a copy of the reference, not access to the caller's variable itself.
Conclusion
- In JavaScript, we have value types, also called primitives, and reference types (non-primitives) which are objects.
- Primitives are number, string, boolean, symbol, undefined, and null, whereas, Non-primitives are objects, functions, and arrays.
- In pass-by value in JavaScript, a copy of the original variable is created, so any changes made to the copied variable do not affect the original variable.
- In pass-by reference in JavaScript, we pass the reference of the actual parameter. No copy is created in the memory.