Pass by value vs pass by reference
"By value" means the variable stores the value itself, so copying creates a new independent copy of the data; "by reference" means the variable stores only a pointer to a place in memory, and it is that pointer that gets copied. In JavaScript primitives behave by value, while objects and every complex data structure behave by reference.
Theory
TL;DR
- Primitives (
number,string,boolean,null,undefined,symbol,bigint) are passed by value. - Objects (
object,array,function,Date,Map,Setand so on) are passed by reference. - A copy of a primitive is fully independent: changing
bdoes not affecta. - A copy of an object is the same structure in memory: a change made through one variable is visible through the other.
- To get an independent object you need a shallow (
{ ...obj }) or a deep copy.
Quick example
// by value
let a = 5;
let b = a; // the value 5 is copied
b = 10;
console.log(a); // 5, unchanged
console.log(b); // 10
// by reference
const user1 = { name: 'Maria' };
const user2 = user1; // the REFERENCE is copied, not the object itself
user2.name = 'Alex';
console.log(user1.name); // "Alex"
console.log(user2.name); // "Alex"What "by value" means
The variable stores the value itself, not a reference to it. Copying creates a new independent copy of the data.
Primitives (simple data types) are passed by value. They are:
numberstringbooleannullundefinedsymbolbigint
let a = 5;
let b = a; // the value 5 is copied
b = 10;
console.log(a); // 5 <- unchanged
console.log(b); // 10a and b are now two independent values, and changing b does not affect a.
What "by reference" means
The variable does not store the object itself, it stores a reference (a pointer) to the place in memory where the object lives.
All objects and complex data structures are passed by reference:
objectarrayfunctionDate,Map,Setand so on
const user1 = { name: 'Maria' };
const user2 = user1; // the REFERENCE is copied, not the object itself
user2.name = 'Alex';
console.log(user1.name); // "Alex"
console.log(user2.name); // "Alex"Both variables point at one and the same object in memory, so changing user2 also changes user1.
Visually:
+------------+
| user1 | --+
+------------+ |
v
{ name: "Maria" }
^
+------------+ |
| user2 | --+
+------------+Example with an array
An array is an object too, so the same rule applies:
const arr1 = [1, 2, 3];
const arr2 = arr1;
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]Both arrays are one and the same object in memory.
How to copy an object without carrying the reference
If you want a new independent object, you have to copy the data explicitly.
A shallow copy (spread):
const user1 = { name: 'Tim', age: 25 };
const user2 = { ...user1 }; // the spread operator
user2.name = 'Alex';
console.log(user1.name); // "Tim"
console.log(user2.name); // "Alex"A deep copy (for nested objects):
const user1 = { name: 'Tim', address: { city: 'Kyiv' } };
const user2 = JSON.parse(JSON.stringify(user1)); // deep cloning
user2.address.city = 'Lviv';
console.log(user1.address.city); // "Kyiv"
console.log(user2.address.city); // "Lviv"Stack, heap and the summary tables
| Type | Where it is stored | What happens on copy |
|---|---|---|
| Primitive (by value) | on the stack | a new copy is created |
| Object (by reference) | on the heap | the reference to the same place is copied |
| Data type | How it is passed | Example |
| --- | --- | --- |
string, number, boolean, null, undefined, symbol, bigint | by value | let a = 5; let b = a; |
object, array, function, Date, Map, Set | by reference | let obj2 = obj1; |
In short:
- By value creates a copy of the data.
- By reference copies the pointer to the same object.
- That is why changing one object affects the other whenever they are linked by a reference.
Common mistakes
- Believing that
constprotects the contents of an object.constforbids reassigning the variable, but it does not forbid changing the fields of the object it points at. - Writing
const copy = originalfor an object and thinking it is a copy. It is a second name for the very same object. - Confusing a shallow copy with a deep one:
{ ...user }copies only the top level, nested objects stay shared. - Reaching for
JSON.parse(JSON.stringify(obj))blindly: it dropsundefined, functions andSymbol, turns aDateinto a string and throws on circular references. For complex cases preferstructuredClone(obj). - Comparing objects with
===and expectingtrue:{ a: 1 } === { a: 1 }isfalse, because those are two different references.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.