Glossary / Finalization and weak references
Finalization and weak references
WeakRef and FinalizationRegistry expose specialized, nondeterministic interactions with garbage collection. A WeakRef allows observation of an object without keeping it alive by that reference alone; a registry can schedule a callback after a target becomes collectible. These APIs are useful for optional caches or cleanup hints, never for correctness-critical behavior.
WeakRef and finalization
const ref = new WeakRef(cacheEntry);
const value = ref.deref();
if (value !== undefined) use(value);
deref() can return undefined after the target has been collected. If it returns an object, keep a strong local reference while using it. Collection may happen at any time from the program’s perspective; there is no guarantee the object will be collected promptly.
FinalizationRegistry receives a held value after a target is collected, but the callback may run much later or not before the process exits. Registry holdings themselves must not strongly retain the target, or collection cannot occur. Callback ordering is not a deterministic lifecycle contract. Use explicit dispose, close, AbortController, or try/finally for resources such as sockets and file handles.
Weak references can add complexity and make tests nondeterministic. They are justified only when losing a cached value is safe and the benefit is measured. A normal bounded cache is often simpler.
Interview questions
- Can a WeakRef keep its target alive? Not solely through the weak reference; other strong references still do.
- Can code rely on a finalizer running? No; it may be delayed or never run before shutdown.
- Should finalization close essential resources? No; explicit cleanup is required.
- Why keep a strong local after deref? It ensures the object remains reachable during the operation.