Skip to main content

Memory Management in JavaScript

How Memory Works

JavaScript automatically allocates memory when values are created and frees it when they are no longer used. This process is called Garbage Collection.

Memory Lifecycle

  1. Allocate — Memory is allocated when you declare variables, objects, or functions.
  2. Use — Read/write operations on the allocated memory.
  3. Release — Memory is freed when it's no longer needed.

Stack vs Heap

FeatureStackHeap
StoresPrimitives & referencesObjects & functions
SizeFixed, smallDynamic, large
AccessFast (LIFO)Slower (random access)
ManagementAutomatic (scope-based)Garbage collected
// Stack: primitive value stored directly
let name = "Ajay"; // stored on stack

// Heap: object stored on heap, reference on stack
let user = { name: "Ajay" }; // reference on stack → object on heap

Garbage Collection

JavaScript uses automatic garbage collection. The main algorithm is Mark-and-Sweep:

  1. The GC starts from root objects (global object, local variables in current scope).
  2. It marks all objects reachable from roots.
  3. It sweeps (frees) all unmarked (unreachable) objects.

Reference Counting (older approach)

Counts how many references point to an object. When count reaches 0, object is freed. Problem: fails with circular references.

// Circular reference — wouldn't be freed by reference counting
function createCycle() {
let a = {};
let b = {};
a.ref = b;
b.ref = a;
// After function returns, mark-and-sweep CAN collect these
// Reference counting would NOT collect them
}

Common Memory Leaks

1. Accidental Globals

function leak() {
name = "oops"; // no let/const/var — creates global variable
}

2. Forgotten Timers

const timer = setInterval(() => {
// holds reference to outer scope
console.log("running...");
}, 1000);

// Fix: clearInterval(timer) when done

3. Detached DOM References

let button = document.getElementById("btn");
document.body.removeChild(button);
// 'button' variable still holds a reference — memory not freed
button = null; // Fix: remove the reference

4. Closures Holding Large Data

function outer() {
let bigData = new Array(1000000).fill("x");
return function inner() {
// inner() keeps bigData alive even if it doesn't use it
console.log("hello");
};
}

WeakRef & WeakMap

Use WeakMap and WeakSet to hold references that don't prevent garbage collection:

let obj = { data: "important" };
let weakMap = new WeakMap();
weakMap.set(obj, "metadata");

obj = null; // object can now be garbage collected
// weakMap entry is automatically removed

Key Takeaways

  • Primitives go on the stack, objects on the heap.
  • JavaScript uses mark-and-sweep garbage collection.
  • Memory leaks happen when references to unused data are accidentally kept alive.
  • Use WeakMap/WeakSet for references that shouldn't prevent GC.