WeakRef & FinalizationRegistry Playground

Explore weak references, GC behavior, cache patterns, object lifecycle, and memory leak prevention

WeakRef Basics

A WeakRef holds a weak reference to an object — it does not prevent garbage collection. deref() returns the object if it is still alive, or undefined if the GC has collected it.
Step-by-step Demo
Code
// Create an object let obj = { data: "important", size: 10000 }; // Create a weak reference const ref = new WeakRef(obj); // Access the object through WeakRef const derefed = ref.deref(); // → { data: "important", size: 10000 } // Drop the strong reference obj = null; // After GC (non-deterministic timing): ref.deref(); // → undefined
Log

FinalizationRegistry

FinalizationRegistry lets you register a callback that fires after an object is garbage collected. The callback receives a held value (not the object itself, since it has been GC'd).
Interactive Demo
Code
const registry = new FinalizationRegistry(heldValue => { console.log(`Object "${heldValue}" was garbage collected`); // Clean up: close connections, release resources, etc. }); let obj = { name: "resource" }; const token = {}; // unregister token registry.register(obj, "resource-id", token); // Later, if you want to prevent the callback: // registry.unregister(token); obj = null; // Object is now eligible for GC // Callback fires at some point after GC
Registry Events

WeakRef Cache Pattern

Use WeakRef to build caches that don't prevent GC. When cached objects are no longer referenced elsewhere, they can be collected, and the cache entry cleaned up via FinalizationRegistry.
WeakRef Cache Implementation
class WeakRefCache { #cache = new Map(); #finRegistry = new FinalizationRegistry(key => { const ref = this.#cache.get(key); if (ref && !ref.deref()) this.#cache.delete(key); }); set(key, value) { this.#cache.set(key, new WeakRef(value)); this.#finRegistry.register(value, key); } get(key) { const ref = this.#cache.get(key); if (!ref) return undefined; const obj = ref.deref(); if (!obj) { this.#cache.delete(key); return undefined; } return obj; } get size() { return this.#cache.size; } }
Cache Events

Object Lifecycle Visualization

Track an object through its lifecycle stages: creation, reference management, GC eligibility, and finalization.
Lifecycle Stages
Object Cards
Timeline

GC Pressure Simulation

Allocate many objects to pressure the garbage collector. Track how many WeakRefs survive after allocation bursts. GC behavior is engine-specific and non-deterministic.
Allocation Burst
Total allocated: 0
WeakRefs alive: 0
Finalization callbacks: 0
GC Events

Strong vs Weak Reference Comparison

Compare how strong references (Map, Set, variables) and weak references (WeakRef, WeakMap, WeakSet) affect object lifetime and garbage collection eligibility.
Side-by-side Comparison
AspectStrong ReferenceWeak Reference
Prevents GCYes — object stays aliveNo — object can be collected
Access guaranteeAlways availableMay return undefined after GC
Memory pressureContributes to pressureDoes not contribute
Use caseData you need to keepCaches, metadata, observers
APIVariables, Map, Set, ArrayWeakRef, WeakMap, WeakSet
CleanupManual (delete, splice, clear)Automatic via GC
NotificationN/AFinalizationRegistry callback
Interactive Demo
Log

Memory Leak Prevention Patterns

Common memory leak sources and how WeakRef/WeakMap/WeakSet help prevent them. These patterns are especially important for long-running applications.
Leak Scenarios
Pattern Analysis
Best Practices
  • Use WeakMap for DOM node metadata — entries auto-clean when nodes are removed
  • Use WeakSet to track visited/processed objects without preventing GC
  • Use WeakRef for caches of expensive-to-create objects
  • Use FinalizationRegistry for cleanup of external resources (file handles, connections)
  • Never rely on finalization for correctness — GC timing is non-deterministic
  • Don't use WeakRef where a strong reference is needed — deref() can return undefined at any time
  • Prefer AbortController for event listener cleanup over WeakRef hacks