Skip to main content

What is a memory leak in JS?

1. What is a memory leak

A memory leak is a situation where a program keeps references to objects that are no longer needed, so the garbage collector (GC) cannot free them from memory.

In other words:

An object is no longer used, but "forgotten" references keep it in memory.


2. How the garbage collector (GC) works

JS has automatic garbage collection. The GC periodically looks for "reachable" objects: those you can get to through references.

Anything with no references (unreachable) gets removed. Anything with at least one reference stays in memory.

The leak problem happens when an object is no longer needed, but a reference to it survives somewhere → the GC still considers it "alive".


3. Common causes of memory leaks in JavaScript

CauseExampleWhat happens
Global variableswindow.obj = { big: 'data' }live until the tab closes
Uncleared timers / intervalssetInterval(() => {...}, 1000) without clearIntervalthe callback keeps a closure and is never freed
Event listenerselement.addEventListener('click', handler) without removeEventListenerthe element is removed, but the handler stays in memory
Closures holding referencesfunctions that close over a context with large objectsthe collector cannot free the context
Caches and data structures (Map, Set)a growing Map without clearing old keysdata is never removed automatically
DOM references after removing an elementconst el = document.getElementById('app'); el.remove();, but the el reference remainsthe element is no longer in the DOM, but hangs in memory

4. Examples of leaks in code

Global variables

javascript
function createLeak() { leak = []; // no let/const -> lands on window for (let i = 0; i < 1000000; i++) leak.push(i); } createLeak(); // leak lives until the tab closes

Timers

javascript
function start() { const data = new Array(1e6).fill('data'); setInterval(() => console.log(data.length), 1000); } start(); // data is never cleared, it's held by the closure

Event handlers

javascript
const btn = document.getElementById('btn'); function handleClick() { console.log('clicked'); } btn.addEventListener('click', handleClick); btn.remove(); // but the listener remains // handleClick and btn stay in memory forever

Unbounded cache

javascript
const cache = new Map(); function heavyCalc(key) { if (cache.has(key)) return cache.get(key); const result = Array(1e5).fill(key); cache.set(key, result); // never cleared return result; }

5. How to detect a memory leak

In the browser (Chrome DevTools)

  1. Open the Memory tab → "Heap snapshot".
  2. Take a memory snapshot (Take snapshot).
  3. Repeat after 10-30 seconds.
  4. Compare: if "Detached DOM nodes" or objects keep growing → a leak.

You can also open the Performance tab → the "Memory" filter → watch the heap size grow.


In Node.js

  • --inspect and Chrome DevTools;
  • clinic.js, node --inspect-brk, heapdump;
  • Monitoring the heap through process.memoryUsage().

6. How to prevent leaks

ProblemSolution
Global variablesalways use let, const
TimersclearTimeout, clearInterval when stopping
Event listenersremoveEventListener on unmount
Closuresdon't keep large objects in scope
Cachesclear old entries (WeakMap, WeakSet)
DOMremove references when removing an element
SPA appswatch cleanup in useEffect, onUnmount

7. "Safe" structures: WeakMap and WeakSet

They do not block the GC, because they hold "weak references".

javascript
let cache = new WeakMap(); function getData(obj) { if (cache.has(obj)) return cache.get(obj); const data = heavyCalculation(obj); cache.set(obj, data); return data; }

If the object obj is no longer used anywhere else, the GC removes it automatically, even if it is still in the WeakMap.


8. Signs of a memory leak

  • Gradual application slowdown;
  • Growing memory (Memory → Heap increasing);
  • UI lag (especially during scrolling/rendering);
  • Frequent garbage collection (GC pauses);
  • Tab crashes ("Aw, Snap!") under large data volumes.

9. Quick summary

WhatDescription
Memory leakholding unneeded objects in memory
Causereferences that are never released
Effectgrowing memory, lag, crashes
DiagnosisChrome DevTools (Memory snapshot)
Fixclean up timers, listeners, caches, DOM references
PreventionWeakMap, WeakSet, cleanup hooks

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.