JavaScript Value vs Reference Types
Everything in JavaScript is an object except primitive types.
Primitive data types are null, undefined, string, number, and boolean.
Complex data types are objects, functions, and arrays.
Primitive Types
Whenever we assign a primitive type to a variable, that variable actually contains the primitive value. This sounds obvious because it is.
When we assign a variable that contains the primitive type to another variable using the assignment operator (=), JS Engine creates a new variable in memory and copies the value of the original variable to this new variable.
var value = 10;
var anotherValue = value;
value = 20;
console.log(value); // 20
console.log(anotherValue); // 10
Changing the original variable will not affect the new variable because the value was copied i.e. value and anotherValue live in a different memory location. Think of this as when you copy an answer from your friend's answer sheet, and after some time your loyal friend changes their answer, that change will not be there in your answer sheet. Right?
Primitive data types are copied by their value.
Complex Types
Whenever we assign a complex type to a variable, the JavaScript engine creates a new object in memory and makes the variable point to that memory location.
var x = { age: 10 };
This line creates a new object in memory and makes the variable x point to that memory location.
Key point: The variable x does not contain the actual object; it just points to it, or refers to it.
When we copy a reference type to another variable using the assignment operator (=), the new variable points to the same location in memory where the actual object exists.
Note that it does not create a brand new object. The new variable acts as an alias—it points to the same object in memory as the original variable but just has a different name.
Complex data types are copied by their reference.
Passing Data Types to Functions
1. Passing Primitive Data Types
When we pass a primitive data type to a function, it is passed by value.
var x = 10;
function fun(y) {
y = 20;
console.log(y); // y is 20
}
fun(x);
console.log(x); // x is 10
When we call the function fun passing x as an argument, here's what happens:
- A new variable named
yis created in memory - The value of variable
xis copied toy - Initially,
yhas a value of 10 - We change the value of
yto 20 - This does not affect
xbecause they are independent variables
Why? Because x and y do not refer to the same memory location. Hence, the value of x is still 10 outside the function.
2. Passing Complex Data Types
When we pass a complex data type to a function, it is passed by reference.
var x = { age: 10 };
function fun(y) {
y.age = 20;
}
fun(x);
console.log(x); // x is { age: 20 }
Since we are passing a complex data type to a function, when the function fun is called, the variable y will also refer to the same location in memory as x.
What this means:
- Both
yandxpoint to the same object in memory - If we mutate
y, the change will also be reflected inx - Logging
xto the console gives{ age: 20 }
Special Case
function fun(x) {
x.age = 10;
x = {
city: 'Noida'
};
}
var y = { age: 12 };
fun(y);
console.log(y); // output - { age: 10 }
In the above example, we are passing an object to function fun and then modifying its property age.
Step by step:
- Since objects are passed by reference, the change
age = 10will reflect in the original object - After that, we reassign
xto a new object{city: "Noida"} - One might think this will also reflect in the original object, but that is wrong
Why?
When we reassign x, a new object is created in memory and x now points to that new object—it is detached from the original object's memory location.
That's why when we log y to the console, it prints {age: 10} (not the new object).
Conclusion
Understanding the difference between value and reference types is crucial for writing bug-free JavaScript code. Here is a quick summary:
Primitive Types (Value Types):
- Stored directly in the variable
- Copied by value when assigned or passed to functions
- Changes to copies don't affect the original
Complex Types (Reference Types):
- Stored as references (pointers) to memory locations
- Copied by reference when assigned or passed to functions
- Changes through one reference affect all references to the same object
Remember: When working with complex data types such as objects, arrays, and functions, you're working with references. Always be mindful of whether you're modifying an existing object or creating a new one!