JavaScript Memory Leaks Interview Questions
One of the most common senior frontend interview questions is:
What is a memory leak in JavaScript?
Interviewers often ask:
- What causes memory leaks?
- How does JavaScript free memory?
- Can closures cause memory leaks?
- How do event listeners leak memory?
- How can memory leaks affect performance?
- How do memory leaks occur in React applications?
Understanding memory leaks is important because they can slowly degrade application performance and eventually crash a browser tab.
1. What is a Memory Leak?
A memory leak occurs when memory that is no longer needed cannot be released.
Example:
Object No Longer Needed
↓
Still Referenced
↓
Cannot Be Garbage Collected
↓
Memory LeakOver time:
More Memory Used
↓
Slower Application
↓
Potential Browser Crash2. Memory Management & Garbage Collection
JavaScript automatically manages memory.
Unlike languages such as C or C++:
delete memory();
free(memory);does not exist.
JavaScript relies on:
Garbage Collection (GC)to reclaim unused memory.
What is Garbage Collection?
Garbage Collection is the process of automatically removing objects that are no longer reachable.
Example:
let user = {
name: "John",
};
user = null;Now:
No References ExistThe object becomes eligible for garbage collection.
Reachability
Garbage collectors determine whether an object is:
Reachableor
UnreachableReachable objects remain in memory.
Unreachable objects can be removed.
Example
let user = {
name: "John",
};Reference:
Global Scope
↓
userObject remains reachable.
Remove Reference
let user = {
name: "John",
};
user = null;Reference removed:
Global Scope
↓
nullThe original object becomes unreachable.
3. Anatomy of a Memory Leak
let users = [];
function addUser() {
users.push({
name: "John",
});
}If:
addUser();is called repeatedly:
Array Grows ForeverMemory usage continues increasing.
4. Common Causes of Memory Leaks
The most common causes are:
- Global Variables
- Closures
- Event Listeners
- Timers
- Detached DOM Elements
- Caches
- React Effects
Let's examine each one.
1. Global Variables
Global variables remain alive for the lifetime of the page.
Example:
var cache = [];Adding data repeatedly:
cache.push(bigObject);without cleanup causes memory growth.
Why Is This a Problem?
Global scope remains reachable until:
Page RefreshTherefore:
Nothing Can Be Collected2. Closures
Closures preserve references to outer variables.
Example:
function createHandler() {
const hugeData = new Array(1000000).fill("data");
return function () {
console.log(hugeData.length);
};
}Why Is This a Leak?
As long as:
handler;exists:
hugeData;cannot be garbage collected.
Visual Representation
handler
↓
Closure
↓
hugeDataReference remains alive.
Important Interview Point
Closures are not memory leaks.
However:
Unnecessary Closure Referencescan create memory leaks.
3. Event Listener Leaks
One of the most common frontend leaks.
Example:
const button = document.getElementById("submit");
button.addEventListener("click", handleClick);Problem
Suppose:
button.remove();The DOM node is removed.
But:
handleClick;still exists as a listener.
The browser may keep references alive.
Solution
Always clean up:
button.removeEventListener("click", handleClick);4. Timer Leaks
Example:
setInterval(() => {
fetchData();
}, 1000);Problem
The interval continues forever.
Even if:
Component Removedor
Feature No Longer Neededthe timer keeps running.
Solution
const id = setInterval(fetchData, 1000);
clearInterval(id);5. Detached DOM Elements
A common browser memory leak.
Example:
const element = document.getElementById("card");
document.body.removeChild(element);DOM node removed.
However:
console.log(element);still references it.
Result
DOM Node Exists In Memoryeven though it is no longer visible.
Visual Representation
JavaScript Variable
↓
Detached DOM NodeThe browser cannot reclaim it.
6. Unbounded Caches
Example:
const cache = {};Store data:
cache[id] = response;If:
Entries Never Removedmemory grows indefinitely.
Real Example
cache["1"] = data;
cache["2"] = data;
cache["3"] = data;
...After months of usage:
Huge Memory ConsumptionSolution
Use:
- Cache limits
- LRU caches
- Expiration strategies
7. React Memory Leaks
A very common interview topic.
Example:
useEffect(() => {
const id = setInterval(() => {
console.log("Running");
}, 1000);
}, []);Problem
Component unmounts.
Interval continues.
Memory leak occurs.
Solution
useEffect(() => {
const id = setInterval(() => {
console.log("Running");
}, 1000);
return () => {
clearInterval(id);
};
}, []);Always clean up effects.
React Event Listener Leak
Bad:
useEffect(() => {
window.addEventListener("resize", handleResize);
}, []);Problem
Listener survives component removal.
Correct
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);React Fetch Request Leak
Example:
useEffect(() => {
fetch("/api/users").then(setUsers);
}, []);Component unmounts before response arrives.
Potential issue:
setUsers(...)runs on an unmounted component.
Better
useEffect(() => {
const controller = new AbortController();
fetch("/api/users", {
signal: controller.signal,
});
return () => {
controller.abort();
};
}, []);Interview Question
Can Closures Cause Memory Leaks?
Answer:
Yes and NoClosures themselves are not leaks.
However:
Closures Keep References AliveIf large objects remain referenced unnecessarily:
Memory Cannot Be FreedInterview Question
Can Garbage Collection Prevent All Memory Leaks?
No.
Garbage collection only removes:
Unreachable ObjectsIf references still exist:
Object Remains Reachableand cannot be collected.
6. How to Detect Memory Leaks
Modern browsers provide:
Chrome DevToolsMemory tools.
Common approaches:
- Heap snapshots
- Allocation timelines
- Performance profiling
Warning Signs
Symptoms include:
- Increasing memory usage
- Slower UI
- Delayed interactions
- Browser tab crashes
- Frequent garbage collection
7. Common Interview Q&A
What is a Memory Leak?
Memory that is no longer needed but cannot be reclaimed because references still exist.
How Does Garbage Collection Work?
Garbage collectors remove unreachable objects.
Reachable objects remain in memory.
Are Closures Memory Leaks?
No.
Closures are normal JavaScript behavior.
Leaks occur when closures unnecessarily retain large objects.
Why Are Event Listeners Dangerous?
Forgotten listeners can keep DOM nodes and objects alive.
Why Are Timers Common Leak Sources?
Intervals and timeouts may continue running after they are no longer needed.
What Causes Most React Memory Leaks?
Typically:
- Uncleaned intervals
- Unremoved event listeners
- Uncancelled requests
- Long-lived subscriptions
Senior-Level Interview Answer
A memory leak occurs when memory that is no longer needed remains reachable and therefore cannot be reclaimed by JavaScript's garbage collector. Since JavaScript uses automatic memory management, developers do not manually free memory, but they are responsible for removing unnecessary references. Common sources of leaks include global variables, closures retaining large objects, event listeners, timers, detached DOM nodes, unbounded caches, and improperly cleaned React effects. Garbage collection can only remove unreachable objects, so memory leaks occur when references remain alive longer than intended.
Common Interview Mistakes
❌ "JavaScript cannot have memory leaks because it has garbage collection."
Correct:
Garbage collection removes only
unreachable objects.❌ "Closures are memory leaks."
Correct:
Closures are normal behavior.
Leaks occur from retained references.❌ "Removing a DOM node frees memory."
Correct:
Only if no references remain.❌ "React automatically prevents memory leaks."
Correct:
Developers must clean up effects,
listeners, and timers.Memory Leak Summary
| Source | Can Cause Leak? |
|---|---|
| Global Variables | ✅ Yes |
| Closures | ✅ Sometimes |
| Event Listeners | ✅ Yes |
| setInterval | ✅ Yes |
| Detached DOM Nodes | ✅ Yes |
| Infinite Cache Growth | ✅ Yes |
| React Effects | ✅ Yes |
Key Takeaways
- Memory Leaks: Occur when unused memory references are not garbage collected because references remain accessible.
- Common Sources: Caused by accidental global variables, unresolved timers (
setInterval), and unremoved DOM event listeners. - Detached DOM: Nodes removed from the page layout but still referenced inside JavaScript variables.
- React Prevention: Always clean up timeouts, event listeners, and API subscriptions inside
useEffectcleanup callbacks.