๐Ÿง  Memory Leak Learning Lab

Interactive examples to understand memory leaks and how to detect them with DevTools.

Example 1: WeakMap vs Map (Cache Scenario)

๐Ÿ“‹ The Scenario

You're caching computed results for user objects. When a user logs out, their data should be garbage collected.

โŒ Problem: Regular Map holds strong references

// This cache PREVENTS garbage collection
const userCache = new Map();

function cacheUserData(user) {
    // user object stored as KEY
    userCache.set(user, {
        computed: heavyComputation(user),
        timestamp: Date.now()
    });
}

// Even after: user = null
// The Map still holds the user object!
// Memory keeps growing...

โœ… Solution: WeakMap allows garbage collection

// This cache ALLOWS garbage collection
const userCache = new WeakMap();

function cacheUserData(user) {
    userCache.set(user, {
        computed: heavyComputation(user),
        timestamp: Date.now()
    });
}

// After: user = null
// WeakMap entry is automatically removed!
// Memory is freed

๐Ÿงช Try It Yourself

1 Open DevTools โ†’ Memory tab
2 Click "Take heap snapshot" (camera icon)
3 Click buttons below to create objects
4 Click the ๐Ÿ—‘๏ธ icon in DevTools to force GC
5 Take another snapshot and compare
Click buttons to start...

Example 2: Closure Holding Large Data

๐Ÿ“‹ The Scenario

You process large data and return a handler function. The closure might keep the large data alive even if you don't need it anymore.

โŒ Problem: Closure keeps large data alive

function createHandler() {
    // Large data - should be temporary
    const largeData = new Array(1000000).fill('x');
    
    // Process it
    const result = largeData.length;
    
    // Return handler that DOESN'T use largeData
    return function handler() {
        console.log('Result:', result);
    };
    
    // But largeData is still in the closure!
    // It can't be garbage collected!
}

โœ… Solution: Null out references

function createHandler() {
    let largeData = new Array(1000000).fill('x');
    
    const result = largeData.length;
    
    largeData = null;  // Release reference!
    
    return function handler() {
        console.log('Result:', result);
    };
    
    // Now largeData can be garbage collected!
}

๐Ÿงช Try It Yourself

Click buttons to start...

Example 3: Detached DOM Nodes

๐Ÿ“‹ The Scenario

You store DOM elements in an array/object. When you remove them from the page, the JavaScript reference keeps them in memory.

โŒ Problem: Array holds removed DOM nodes

const elements = [];

function addCard() {
    const card = document.createElement('div');
    card.innerHTML = '<img src="large-image.jpg">';
    container.appendChild(card);
    elements.push(card);  // Store reference
}

function removeCards() {
    elements.forEach(el => el.remove());
    // DOM nodes removed from page...
    // But 'elements' array still holds them!
    // They're "detached" but not garbage collected
}

๐Ÿงช Try It Yourself

Click buttons to start...

๐Ÿ“– DevTools Memory Tab Guide

Opening Memory Tab

๐Ÿ”ง Key Features

1. Heap Snapshot (๐Ÿ“ธ Most Useful)

2. Allocation Timeline

3. Allocation Sampling

๐Ÿ” Finding Leaks with Snapshots

1 Take initial snapshot (baseline)
2 Perform the action you suspect leaks (e.g., open/close modal 5 times)
3 Click ๐Ÿ—‘๏ธ (garbage bin icon) to force GC
4 Take second snapshot
5 In the dropdown, select "Comparison" and compare to Snapshot 1
6 Look at "# Delta" column - positive = more objects = potential leak

๐Ÿ”Ž Useful Filters in Heap Snapshot

๐Ÿ’ก Pro Tips


๐ŸŽฏ Quick Exercise

  1. Take a heap snapshot (baseline)
  2. Click "Create 1000 Users (Map)" above
  3. Click "Clear All References"
  4. Force GC (๐Ÿ—‘๏ธ icon)
  5. Take another snapshot
  6. Use "Comparison" view - you'll see 1000 objects still there!
  7. Now refresh page and try with WeakMap instead
  8. After clearing refs + GC, WeakMap entries are gone