Signatur
Beschreibung
Mit new WeakRef(target) legst du ein WeakRef-Objekt an, das eine schwache Referenz auf target hält. Bei einer normalen (starken) Referenz bleibt ein Objekt so lange im Speicher, wie irgendwo darauf verwiesen wird. Eine schwache Referenz hält das Objekt dagegen nicht fest: Gibt es keine starken Referenzen mehr, darf der Garbage Collector es jederzeit freigeben.
Auf das Zielobjekt greifst du über WeakRef.prototype.deref() zu. Die Methode liefert das Objekt zurück, solange es noch existiert, und danach undefined. Typische Einsatzgebiete sind Caches für große, jederzeit neu erzeugbare Objekte (z. B. dekodierte Bilder, geparste Daten) und das Beobachten von DOM-Elementen, ohne sie künstlich am Leben zu halten.
WeakRef muss mit new aufgerufen werden. Als Ziel sind nur Objekte und nicht registrierte Symbole erlaubt, keine primitiven Werte. Häufig wird WeakRef zusammen mit FinalizationRegistry eingesetzt, damit man nach der Freigabe aufräumen kann (etwa verwaiste Einträge aus einer Map entfernen).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | object | symbol | Das Objekt, auf das schwach verwiesen werden soll. Seit ES2023 sind auch nicht registrierte Symbole erlaubt (also keine per Symbol.for() erzeugten). Primitive Werte lösen einen TypeError aus. |
Rückgabewert
WeakRef-Objekt, das schwach auf target verweist.Beispiele
WeakRef erzeugen und mit deref() auslesen
let user = { name: 'Anna', rolle: 'admin' };
const ref = new WeakRef(user);
// Solange eine starke Referenz besteht, ist das Objekt erreichbar
console.log(ref.deref()?.name);
// Starke Referenz aufheben – ab jetzt darf der GC das Objekt freigeben
user = null;
// Irgendwann später (nicht vorhersagbar):
// ref.deref() === undefined
Cache für aufwendig berechnete Objekte
const cache = new Map();
const registry = new FinalizationRegistry((key) => {
// Eintrag nur löschen, wenn er nicht inzwischen ersetzt wurde
const ref = cache.get(key);
if (ref && !ref.deref()) cache.delete(key);
});
const ladeDaten = (key) => {
const vorhanden = cache.get(key)?.deref();
if (vorhanden) return vorhanden;
const daten = { key, werte: new Array(100_000).fill(key.length) };
cache.set(key, new WeakRef(daten));
registry.register(daten, key);
return daten;
};
const a = ladeDaten('bericht-2024');
const b = ladeDaten('bericht-2024');
console.log(a === b);
DOM-Element beobachten, ohne es festzuhalten
const el = document.createElement('div');
document.body.append(el);
const elRef = new WeakRef(el);
const timer = setInterval(() => {
const node = elRef.deref();
if (!node || !node.isConnected) {
console.log('Element entfernt – Timer wird beendet');
clearInterval(timer);
return;
}
node.textContent = new Date().toLocaleTimeString('de-DE');
}, 1000);
// Später: el.remove();
Ungültige Ziele lösen TypeError aus
try {
new WeakRef(42);
} catch (err) {
console.log(err instanceof TypeError);
}
try {
WeakRef({}); // ohne new
} catch (err) {
console.log(err.constructor.name);
}
// Wichtig · Fallstricke
- Nicht deterministisch: Wann (und ob überhaupt) der Garbage Collector ein Objekt freigibt, hängt von der Engine ab. Programmlogik darf nie davon abhängen, dass
deref()zu einem bestimmten Zeitpunktundefinedliefert. - Innerhalb desselben synchronen Durchlaufs (Job) bleibt ein per
deref()erhaltenes oder mitnew WeakRef()frisch referenziertes Ziel garantiert erhalten. Ergebnis vonderef()deshalb in einer lokalen Variable speichern, statt mehrfach aufzurufen. - Primitive Werte und registrierte Symbole (
Symbol.for()) alstargetführen zu einemTypeError, ebenso ein Aufruf ohnenew. - Nutze
WeakRefsparsam: Für reine Zuordnungen von Metadaten zu Objekten sindWeakMapbzw.WeakSetmeist die bessere, einfachere Wahl. - Kompatibilität: Chrome/Edge 84+, Firefox 79+, Safari 14.1+, Node.js 14.6+. Symbole als Ziel erst ab ES2023 (neuere Engines).