stackademic

The leading education platform for anyone with an interest in software development.

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