When you dive into JavaScript, one thing becomes quickly obvious: memory management feels like magic.
You create variables, objects, arrays, functions and somehow, it all just works.
But here’s the twist: just because JavaScript does the heavy lifting doesn’t mean you should ignore memory altogether.
In this post, we’ll break down how JavaScript manages memory behind the scenes, what reachability means, and why it’s still important for you to know it.
Memory: Manual vs Automatic
In languages like C, if you forget to free()
a chunk of memory after malloc()
, you’re inviting a leak. In JavaScript, memory allocation happens when you create things:
const spaceship = {
name: "Odyssey",
crew: 5
};
…and when your spaceship is no longer needed, JavaScript’s garbage collector swoops in to clean up. Sounds easy, right?
Well, it is, but understanding when and why memory gets cleared can save you from mysterious performance issues down the line.
What is Reachability?
The whole game revolves around one concept: reachability.
A value is called reachable if it can be accessed or used.
If a value becomes unreachable, meaning there’s no way to get to it anymore, it becomes a candidate for garbage collection.
Roots are your starting points:
- Global variables
- Local variables in currently running functions
- Function parameters
-
this
inside methods
From there, anything connected (directly or indirectly) is also considered reachable.
Simple Example
let rocket = { model: "Falcon 9" };
// Later...
rocket = null;
When we assign rocket = null
, we break the reference. The object { model: "Falcon 9" }
is now unreachable and will eventually be collected.
Two References, One Object
let pilot = { name: "Amelia" };
let coPilot = pilot;
pilot = null;
Even though pilot
is nullified, coPilot
still holds a reference to the same { name: "Amelia" }
object. So Amelia's memory is safe — for now.
If we later do:
coPilot = null;
Now there are no references, and Amelia can be collected.
Interlinked Objects: A Family Portrait
Things get interesting when objects reference each other:
function teamUp(hero, sidekick) {
hero.partner = sidekick;
sidekick.leader = hero;
return { hero, sidekick };
}
let alliance = teamUp({ name: "Batman" }, { name: "Robin" });
In this scenario, Batman knows Robin, and Robin knows Batman.
The alliance
object links them both.
If you remove those references:
delete alliance.hero;
delete alliance.sidekick.leader;
But do not remove all incoming references, they might still stay in memory. To truly let them go:
alliance = null;
Now there’s no root access to Batman or Robin. They’re trapped in an isolated “memory island” — unreachable — and the garbage collector will clear them out.
Under the Hood: Mark-and-Sweep
Garbage collection mostly works through a mark-and-sweep algorithm:
- Start from the roots.
- Mark every reachable object.
- Sweep away (delete) anything not marked.
It’s like dumping a bucket of paint at the roots and letting it flow through all references. Anything left unpainted? Gone.
Cool Optimizations Engines Use
Modern JavaScript engines like V8 (used in Chrome and Node.js) have made garbage collection super efficient:
- Generational GC: Young objects die young; old objects get checked less frequently.
- Incremental GC: Instead of freezing your app to collect everything at once, GC happens in small slices.
- Idle-time GC: GC runs when your app isn’t busy, making collections invisible to users.
These tricks ensure your apps stay snappy, without you even realizing memory cleanup is happening.
Why Should You Care?
Because memory leaks still happen even in JavaScript. Here’s how:
- Keeping references in global scope you forgot about
- Circular references in closures or event listeners
- Detached DOM elements being referenced in JavaScript variables
Understanding reachability and memory cleanup helps you write faster, more efficient code.
Final Thoughts
You don’t have to manage memory manually in JavaScript (thankfully 😅).
But knowing how it works gives you an edge.
Remember:
- Only unreachable values are collected.
- Objects can survive even if you think you’ve abandoned them.
- Leaks happen more often by accident than intent.
If you want to go deeper into memory internals, especially for engines like V8, I recommend checking out the V8 team's official blog and The Garbage Collection Handbook.
I’ve been actively working on a super-convenient tool called LiveAPI.
LiveAPI helps you get all your backend APIs documented in a few minutes
With LiveAPI, you can quickly generate interactive API documentation that allows users to execute APIs directly from the browser.
If you’re tired of manually creating docs for your APIs, this tool might just make your life easier.