JavaScript Memory Management

How allocation, garbage collection, and leaks work in JavaScript

Overview

JavaScript allocates memory automatically when you create values and frees it with a garbage collector. The collector uses reachability: any value reachable from a root (globals, the call stack, active closures) is kept, and everything else is eligible for collection. Memory leaks happen when references linger longer than needed.

Syntax / Usage

You rarely manage memory manually, but you control reachability by holding or dropping references. WeakMap, WeakSet, and WeakRef let you reference objects without preventing their collection.

let cache = new Map()
cache.set('user:1', { name: 'Ada' }) // strong reference, stays alive

// A WeakMap does not keep its keys alive
const meta = new WeakMap()
let node = { id: 1 }
meta.set(node, { visited: true })

node = null // the object (and its WeakMap entry) can now be collected

Examples

Closures keep referenced variables alive—retain only what you need:

function createCounter() {
  let count = 0 // captured by the returned closure, stays in memory
  return () => ++count
}

const next = createCounter()
console.log(next(), next()) // 1 2

A detached DOM reference is a classic leak; clearing it lets memory free up:

let detached = []

function leak() {
  const el = document.createElement('div')
  detached.push(el) // array keeps every element reachable forever
}

function cleanup() {
  detached = [] // drop references so the collector can reclaim them
}

Forgotten timers hold their callbacks (and captured scope) alive:

function startPolling(getData) {
  const id = setInterval(() => getData(), 1000)
  return () => clearInterval(id) // return a disposer to stop the leak
}

const stop = startPolling(() => {})
stop() // without this, the interval and closure live forever

Common Mistakes

  • Accumulating entries in a long-lived Map or array without ever removing them
  • Forgetting to clearInterval/clearTimeout or remove event listeners
  • Holding large objects in closures that outlive their usefulness
  • Assuming setting a variable to null frees memory when other references still exist
  • Using Map where WeakMap is appropriate, preventing key objects from being collected

See Also

closures objects javascript-event-loop