ResourcesJavascriptGuides

Reference types in Javascript

Introduction

In JavaScript, the distinction between primitive and reference data types is confusing for programmers.

In this guide we will explain the difference and focus mostly on how reference works in Javascript.

We have an article with all data types in javascript here: Data Types in Javascript


Difference Between Primitive and Reference Data Types

Primitive data types

Primitive data types include Number, String, Boolean, null, undefined, Symbol, and BigInt.

They are immutable and stored directly in the variable.

Reference data types

Reference data types include Object, Array, and Function.

They store a reference (memory address) to the actual value, not the value itself.

Key differences

  • Primitives are copied by value.
  • Reference types are copied by reference, meaning variables share the same memory location.

What it memory reference?

When assigning a reference data type to another variable, both variables point to the same memory location.

In computer science terms, when you create an object or an array, Javascript allocates a space in memory for that entity. For instance, consider an object stored in memory at address 0x0001.

let obj1 = { name: 'Alice' };
let obj2 = obj1;
obj2.name = 'Bob';
 
console.log(obj1.name); // Output: Bob
console.log(obj2.name); // Output: Bob

In the above example, obj1 is created and stored at memory address 0x0001. When obj2 is assigned to obj1, it does not create a new object.

Instead, obj2 holds the reference to the same memory address 0x0001. So, any changes made through obj2 reflect in obj1 because both variables point to the same location in memory.

Let's look at it visually:

Memory Address      Variable       Value
0x0001              obj1           { name: 'Alice' }
0x0001              obj2           { name: 'Alice' } (After assignment, both point to the same address)

After changing obj2.name to Bob:

Memory Address      Variable       Value
0x0001              obj1           { name: 'Bob' }
0x0001              obj2           { name: 'Bob' }

Tricky examples 🍬

Object Assignment

let original = { name: 'Alice' };
let copy = original;
copy.name = 'Bob';
 
console.log(original.name); // Output: Bob
console.log(copy.name); // Output: Bob

To avoid referencing the same memory location, use Object.assign or even better the spread operator (...).

Example with spread operator:

let original = { name: 'Alice' };
let copy = { ...original };
copy.name = 'Bob';
 
console.log(original.name); // Output: Alice
console.log(copy.name); // Output: Bob

Arrays

Arrays are reference types too, so they have similar behavior.

let arr1 = [1, 2, 3];
let arr2 = arr1;
arr2.push(4);
 
console.log(arr1); // Output: [1, 2, 3, 4]
console.log(arr2); // Output: [1, 2, 3, 4]

To avoid referencing the same memory location, use the spread operator (...) or Array.from.

let arr1 = [1, 2, 3];
let arr2 = [...arr1];
arr2.push(4);
 
console.log(arr1); // Output: [1, 2, 3]
console.log(arr2); // Output: [1, 2, 3, 4]

Best practices

  • Avoid unintended mutations: Always be cautious when assigning reference types to multiple variables.
  • Use deep cloning: For nested objects, use libraries like Lodash or structured cloning algorithms for deep cloning.

Example with loadash:

let _ = require('lodash');
let original = { name: 'Alice', address: { city: 'Wonderland' } };
let copy = _.cloneDeep(original);
copy.address.city = 'New Wonderland';
 
console.log(original.address.city); // Output: Wonderland
console.log(copy.address.city); // Output: New Wonderland

Summary

Understanding how reference works in Javascript is quite important yet a lot of new developers procrastinate on it. Not knowing how objects work can lead to huge bugs in your production code while trying to copy or reassign values.

Please understand and study this topic deeply, it's not that hard.

Resources

MDN Web docs

On this page