Last modified: Jul 21, 2026

JS Variable Reference vs Value

Understanding how JavaScript handles variables is crucial. One of the most common points of confusion for beginners is the difference between value and reference. This article will explain this concept clearly with simple examples.

In JavaScript, how a variable behaves depends on the type of data it holds. Primitive types (like numbers, strings, booleans) are copied by value. Objects (including arrays and functions) are copied by reference.

What Does "Copy by Value" Mean?

When you assign a primitive value to a variable, the actual data is stored directly in that variable. If you assign that variable to another, a new, independent copy of the value is created.

This means changing the second variable does not affect the first. They are two separate containers holding the same number, but they are not connected.

Let's look at an example with numbers.


// Primitive example: numbers
let a = 10;
let b = a; // 'b' gets a copy of the value 10

console.log("a before:", a); // Output: 10
console.log("b before:", b); // Output: 10

b = 20; // We change 'b' only

console.log("a after:", a); // Output: 10 (unchanged!)
console.log("b after:", b); // Output: 20

As you can see, b is a separate copy. Changing b to 20 did not affect a. This is the core of "copy by value".

What Does "Copy by Reference" Mean?

Objects are different. An object variable does not store the object itself. Instead, it stores a reference (a memory address) that points to the object's location.

When you assign an object to another variable, you copy the reference, not the object. Both variables now point to the same object in memory.

Therefore, changing the object through one variable will affect the other variable as well.


// Reference example: objects
let person1 = { name: "Alice", age: 30 };
let person2 = person1; // 'person2' gets a reference to the same object

console.log("person1.name before:", person1.name); // Output: Alice
console.log("person2.name before:", person2.name); // Output: Alice

person2.name = "Bob"; // We modify the object through 'person2'

console.log("person1.name after:", person1.name); // Output: Bob (changed!)
console.log("person2.name after:", person2.name); // Output: Bob

Here, person1 and person2 are two keys to the same house. Changing the name inside the house affects both keys.

Comparison: Primitive vs Object

This distinction is vital for comparing variables. When you use the strict equality operator ===:

  • Primitives: It compares the actual values.
  • Objects: It compares the references (do they point to the same object?).

Two objects that look identical are considered different if they are stored in different memory locations.


// Comparison examples
let x = 5;
let y = 5;
console.log(x === y); // Output: true (same value)

let objA = { value: 10 };
let objB = { value: 10 };
console.log(objA === objB); // Output: false (different references)

let objC = objA; // objC now points to the same object as objA
console.log(objA === objC); // Output: true (same reference)

How Functions Handle Value and Reference

This behavior is also critical when passing variables to functions. When you pass a primitive to a function, the function receives a copy of the value. Changes inside the function do not affect the original variable.

When you pass an object to a function, the function receives a copy of the reference. The function can modify the original object's properties.


// Function with primitive
function changePrimitive(val) {
    val = 100;
}

let myNum = 50;
changePrimitive(myNum);
console.log("myNum after function:", myNum); // Output: 50 (unchanged)

// Function with object
function changeObject(obj) {
    obj.name = "Updated";
}

let myObj = { name: "Original" };
changeObject(myObj);
console.log("myObj.name after function:", myObj.name); // Output: Updated (changed)

Creating a True Copy of an Object

Sometimes you want to copy an object by value, not by reference. You need to create a new, independent object. This is called a shallow copy.

For simple objects, you can use the spread operator (...) or Object.assign(). These methods copy the top-level properties by value, but nested objects are still copied by reference.


// Shallow copy using spread operator
let original = { a: 1, b: 2 };
let copy = { ...original };

copy.a = 10;

console.log("original.a:", original.a); // Output: 1 (unchanged)
console.log("copy.a:", copy.a);         // Output: 10

For deeply nested objects, you might need a deep copy. A simple way is using JSON.parse(JSON.stringify(obj)), but be aware it does not work for functions or special object types.

Common Mistakes and Best Practices

A frequent mistake is accidentally mutating an object that was meant to be a copy. This often happens when you pass an array or object to a function and expect the original to stay unchanged.

To avoid this, always be aware of what you are passing. When you need a separate copy, create one explicitly using the methods mentioned above.

Understanding this concept will help you debug many confusing bugs. It is a fundamental part of learning JavaScript.

For more foundational knowledge, check out our guide on JavaScript Variable Declaration Guide. You can also learn about JavaScript Variable Scope Explained to understand where your variables live. Finally, see practical usage in our JavaScript Variables Examples.

Conclusion

The distinction between value and reference is a cornerstone of JavaScript. Primitives are copied by value, creating independent copies. Objects are copied by reference, meaning multiple variables can point to the same data.

Always remember this when assigning variables or passing them to functions. It will save you from many hours of debugging. Practice with small code snippets to solidify this concept in your mind.

Mastering this topic is a big step toward becoming a more confident JavaScript developer.