Signatur
Beschreibung
Der Konstruktor FinalizationRegistry() erzeugt eine Registry. Mit register() meldet man dort Objekte an. Wird ein angemeldetes Objekt später von der Garbage Collection eingesammelt, ruft die Engine den übergebenen callbackFn auf. Dabei bekommt der Callback den Held Value, den man bei der Registrierung angegeben hat, und nicht das Objekt selbst, denn das existiert zu diesem Zeitpunkt nicht mehr.
Typische Einsatzfälle sind Aufräumarbeiten für externe Ressourcen, die an JavaScript-Objekte gekoppelt sind. Dazu gehören etwa Speicher in WebAssembly, native Handles, Einträge in Caches mit WeakRef-Werten oder Datei- und Socket-Handles in Node.js. Oft kombiniert man die Registry mit WeakRef, um Caches zu bauen, die sich selbst bereinigen.
Wichtig: Finalisierung ist nicht deterministisch. Die Spezifikation garantiert weder, wann der Callback läuft, noch ob er überhaupt läuft, etwa wenn das Programm vorher endet. Die Registry eignet sich deshalb nur als Sicherheitsnetz oder zur Optimierung, nie für Logik, die für das Programm wichtig ist.
Der Konstruktor muss mit new aufgerufen werden. Ein Aufruf ohne new wirft einen TypeError.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $callbackFn Pflicht | (heldValue: any) => void | Funktion, die nach dem Einsammeln eines registrierten Objekts aufgerufen wird. Sie erhält als einziges Argument den heldValue, der bei register(target, heldValue) übergeben wurde. Ihr Rückgabewert wird ignoriert. Ist callbackFn keine Funktion, wird ein TypeError geworfen. |
Rückgabewert
FinalizationRegistry-Objekt mit den Methoden register() und unregister().Beispiele
Registry erstellen und Objekt registrieren
const registry = new FinalizationRegistry((heldValue) => {
console.log(`Objekt eingesammelt: ${heldValue}`);
});
let user = { name: 'Anna' };
registry.register(user, 'user-Anna');
// Referenz entfernen – das Objekt kann jetzt eingesammelt werden
user = null;
// Irgendwann später (nicht garantiert):
Selbstbereinigender Cache mit WeakRef
class WeakCache {
#map = new Map();
#registry = new FinalizationRegistry((key) => {
// Nur löschen, wenn der Eintrag noch tot ist (kein neuer Wert unter dem Schlüssel)
const ref = this.#map.get(key);
if (ref && !ref.deref()) this.#map.delete(key);
});
set(key, value) {
this.#map.set(key, new WeakRef(value));
this.#registry.register(value, key);
}
get(key) {
return this.#map.get(key)?.deref();
}
}
const cache = new WeakCache();
const bild = { pixels: new Uint8Array(1024) };
cache.set('logo', bild);
console.log(cache.get('logo') === bild);
Explizites Freigeben mit Unregister-Token
const registry = new FinalizationRegistry((handle) => {
console.warn(`Ressource ${handle} wurde nicht geschlossen – räume auf.`);
});
class FileHandle {
constructor(id) {
this.id = id;
// this dient als Unregister-Token
registry.register(this, id, this);
}
close() {
console.log(`Schließe ${this.id}`);
registry.unregister(this); // Sicherheitsnetz nicht mehr nötig
}
}
const f = new FileHandle('datei-42');
f.close();
// Wichtig · Fallstricke
- Keine Garantie: Ob und wann der Callback läuft, hängt von der Engine, vom Speicherdruck und von der Laufzeit ab. Ressourcen sollte man immer ausdrücklich freigeben, etwa mit
close()oderusing. Die Registry dient nur als Absicherung. - Kein Verweis auf das Ziel: Der
heldValuedarf nicht das registrierte Objekt selbst sein, sonst wirftregister()einenTypeError. Er sollte das Objekt auch nicht indirekt referenzieren, weil es sonst nie eingesammelt wird. Auch der Callback selbst darf das Ziel nicht über eine Closure festhalten. - Der Callback läuft asynchron in einem eigenen Job, nicht während der Garbage Collection. Ausnahmen im Callback werden als unbehandelte Fehler gemeldet.
- Primitive Werte können nicht registriert werden. Nicht registrierte Symbole sind erst seit ES2023 erlaubt.
- Kompatibilität: Chrome 84+, Firefox 79+, Safari 14.1+, Node.js 14.6+. In älteren Umgebungen ist keine Nachrüstung per Polyfill möglich.
- Zum Testen lässt sich in Node.js mit
node --expose-gcundglobal.gc()eine Garbage Collection erzwingen. Auch dann ist das Verhalten nicht garantiert.