JavaScript Memory Management & Garbage Collection Guide
What is Garbage Collection?
Garbage collection (GC) is the process of automatically freeing up memory that is no longer being used by a program. In JavaScript, when you declare variables, objects, or functions, memory is allocated to store them. When these are no longer needed, the garbage collector identifies and clears them from memory.
Key Point: JavaScript is a high-level language with automatic memory management. You don’t manually allocate or free memory – the JavaScript engine handles this for you through garbage collection.
Memory Lifecycle in JavaScript
The memory lifecycle in JavaScript consists of three phases:
| Phase | Description | Example |
|---|---|---|
| Allocation | Memory is allocated when you declare variables, create objects or functions | let obj = { name: "John" }; |
| Usage | Reading and writing to allocated memory | console.log(obj.name); |
| Release | Freeing memory when it’s no longer needed (handled by GC) | obj = null; // Makes object eligible for GC |
Reachability: The Key Concept
The main concept behind garbage collection is reachability. Values that are accessible or usable are called “reachable” and are kept in memory.
Understanding Reachability
// Initially, the object is reachable via the 'obj' reference
let obj = { name: "Orange" };
// Now we have two references to the same object
let obj2 = obj;
// Removing one reference - the object is still reachable via obj2
obj = null;
// Removing the last reference - the object is now unreachable
obj2 = null;
// The { name: "Orange" } object is now eligible for garbage collection
Object is reachable
Object still reachable via obj2
Object is unreachable (eligible for GC)
The Mark-and-Sweep Algorithm
Modern JavaScript engines use the mark-and-sweep algorithm for garbage collection. This algorithm works in two phases:
- Mark: The garbage collector starts from “roots” (global variables) and marks all references that are reachable.
- Sweep: The garbage collector sweeps through memory and removes objects that weren’t marked (unreachable).
Mark-and-Sweep Process
// Global object (root)
let globalObj = {
refA: {
name: "A"
}
};
// Another reference
let refB = {
name: "B",
refC: {
name: "C"
}
};
// Creating a circular reference (not a problem for mark-and-sweep)
globalObj.refA.refB = refB;
refB.refC.refA = globalObj.refA;
// Removing references
refB = null;
// The mark-and-sweep algorithm will correctly identify
// which objects are still reachable from the root (globalObj)
Memory Leaks in JavaScript
Despite automatic garbage collection, memory leaks can still occur in JavaScript. Common causes include:
| Cause | Description | Prevention |
|---|---|---|
| Accidental Global Variables | Variables declared without var/let/const become global | Always declare variables properly |
| Forgotten Timers/Callbacks | setInterval or event listeners that aren’t cleaned up | Clear intervals and remove event listeners |
| Closures | Holding references to large objects unnecessarily | Be mindful of what closures capture |
| Detached DOM Elements | DOM elements removed from DOM but referenced in JavaScript | Nullify references to removed DOM elements |
Circular Reference Example (Historical)
// In older browsers, circular references could cause memory leaks
function createLeak() {
let teacher = new Teacher();
let student = new Student();
// Circular reference
teacher.student = student;
student.teacher = teacher;
return teacher;
}
// Modern garbage collectors (mark-and-sweep) handle this correctly
// The objects will be collected when no longer reachable
Best Practices for Memory Management
- Use
letandconstinstead ofvarfor block scoping - Avoid creating unnecessary global variables
- Nullify references to large objects when no longer needed
- Clean up event listeners and timers when done
- Be cautious with closures that capture large objects
- Use developer tools to profile memory usage