Understanding Primitives and References in JavaScript

NicolasBrondinBernard

Author
@NicolasBrondinBernard

You don't always need to know the inner workings of the language, but some concepts are essential!

Article published on 16/02/2021, last updated on 10/08/2026

In JavaScript, not all data is handled the same way, nor stored in the same place in memory, which can be confusing and lead to a few errors, so let's take a look together to understand all these subtleties.

When you declare and initialize a new variable, you're going to reserve a space in the machine's memory.

Generally in RAM, the random access memory.

This space will be more or less large depending on the data you need to store there (1 bit for a boolean, 8 bits for a character, etc...), the goal being for your program to take up as little space as possible in memory, and above all not to waste space unnecessarily.

While it's possible to know in advance the size of a piece of data for certain types (such as booleans), this is not the case for all of them, such as complex types for example (object, array, function, etc...)

That's why JavaScript provides two broad, quite distinct types of data: primitive data and references.

Primitive types

There are 7 of them in JavaScript, and they are: string, number, bigint, boolean, undefined, null and symbol.

The main characteristic of these types is that their values are "immutable", which means they cannot change.

But when I declare a new string, I can change its value!

You'd think so, but actually no.

Each new piece of data is stored at a very specific memory address (where the data begins), and when you modify a primitive, you're not modifying the value at the memory address's location, but you're requesting a new available address to store this new piece of data.

Example:


let nbr = 5; //The (fictional) address 0x0001 contains the number 5
nbr = 3; //A new address 0x0002 now contains the number 3

//Memory slot 0x0001 will be freed as soon as possible, since it's no longer used

A primitive value is never altered, the variable pointing to it can be reassigned (except with const) but the value itself won't be modified.

To prove it to yourself, you can try this little experiment, directly in your console:


let a = "hello"; //Address 0x0001
let b = a; //Address 0x0001

a += " world" //Address 0x0002
console.log(a); // -> "hello world";
console.log(b); // -> "hello";

As you can see, even though variable b points to the same address as variable a at the start, when we modify the value of a, the value of b doesn't change, because a new memory address has been assigned to variable a.

Primitive values are therefore stored in a space called "static" memory, also known as the "stack".

References

Unlike primitive values, complex values are stored in the "dynamic" part of memory because their size is variable and can evolve as the program runs, making them "unpredictable".

Imagine a variable needs 8 bits of space to be stored, if the operating system finds a free 8-bit space between two other pieces of data, then it will be able to use that space and dedicate it to this new variable.

But now let's imagine our variable no longer needs 8 bits but 16, because it has grown, then our variable will no longer fit at its current address and will need to be moved elsewhere in memory.

So we need a variable that no longer contains a simple value, but instead contains a reference to a memory address that can change, this reference is therefore dynamic and must point to the object, wherever it is located in memory.

This is what's known as dynamic memory, also called the "heap".

This leads to different behavior when modifying a variable.

We no longer modify the value behind the variable, but the value behind the reference behind the variable, so if several variables contain the same reference, modifying the object will affect all the variables pointing to it.

Example:


let a = {txt: "hello"}; //Reference r0 to the object
let b = a; //Reference r0 to the same object

a.txt += " world" //Address 0x0002
console.log(a); //"hello world";
console.log(b); //"hello world";

Our two variables therefore no longer store values, but references to the same value, which can change.


Ksenia Kudelkina sur Unsplash

Finished reading this article?
Our complete courses
Take it to the next level with our courses!

Complete courses, exercises and certificates to really learn programming!

4.8 average rating

Comments (0)

to leave a comment

No comments yet