WeakRef
Baseline Widely available *
This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2021.
* Some parts of this feature may have varying levels of support.
Ein WeakRef
-Objekt ermöglicht es Ihnen, eine schwache Referenz auf ein anderes Objekt zu halten, ohne das Objekt daran zu hindern, vom Garbage Collector entfernt zu werden.
Beschreibung
Ein WeakRef
-Objekt enthält eine schwache Referenz auf ein Objekt, das als Ziel oder Referent bezeichnet wird. Eine schwache Referenz auf ein Objekt ist eine Referenz, die nicht verhindert, dass das Objekt vom Garbage Collector wieder freigegeben wird. Im Gegensatz dazu hält eine normale (oder starke) Referenz ein Objekt im Speicher. Wenn ein Objekt keine starken Referenzen mehr hat, kann der Garbage Collector der JavaScript-Engine das Objekt zerstören und seinen Speicher freigeben. Sollte dies geschehen, können Sie das Objekt nicht mehr aus einer schwachen Referenz abrufen.
Da nicht registrierte Symbole ebenfalls sammelbar sind, können sie auch als Ziel eines WeakRef
-Objekts verwendet werden. Der Anwendungsfall dafür ist jedoch begrenzt.
Wo möglich vermeiden
Die korrekte Verwendung von WeakRef
erfordert sorgfältiges Überlegen, und es ist am besten, sie zu vermeiden, wenn möglich. Es ist auch wichtig, sich nicht auf spezifische Verhaltensweisen zu verlassen, die von der Spezifikation nicht garantiert werden. Wann, wie und ob eine Speicherbereinigung erfolgt, hängt von der Implementierung der jeweiligen JavaScript-Engine ab. Ein Verhalten, das Sie in einer Engine beobachten, kann in einer anderen Engine, in einer anderen Version derselben Engine oder sogar in einer leicht abgewandelten Situation mit derselben Version der gleichen Engine anders sein. Speicherbereinigung ist ein schwieriges Problem, das die Implementierer von JavaScript-Engines ständig verfeinern und verbessern.
Hier sind einige spezifische Punkte, die in dem Vorschlag enthalten sind, der WeakRef
eingeführt hat:
Garbage Collectors sind kompliziert. Wenn eine Anwendung oder Bibliothek darauf angewiesen ist, dass GC eine WeakRef aufräumt oder einen Finalizer [aufräum-Callback] rechtzeitig und vorhersehbar aufruft, wird sie vermutlich enttäuscht sein: Die Bereinigung kann viel später als erwartet erfolgen oder gar nicht. Variabilitätsquellen sind unter anderem:
- Ein Objekt könnte viel früher als ein anderes Objekt gesammelt werden, selbst wenn sie gleichzeitig unerreichbar werden, z.B. aufgrund von Generationssammlung.
- Die Arbeit der Speicherbereinigung kann über die Zeit mittels inkrementellen und nebenläufigen Techniken verteilt werden.
- Verschiedene Laufzeit-Heuristiken können verwendet werden, um den Speicherverbrauch und die Reaktionsfähigkeit auszugleichen.
- Die JavaScript-Engine kann Referenzen auf Dinge halten, die scheinbar nicht erreichbar sind (z.B. in Closures oder Inline-Caches).
- Verschiedene JavaScript-Engines können diese Dinge unterschiedlich tun, oder die gleiche Engine kann ihre Algorithmen über Versionen hinweg ändern.
- Komplexe Faktoren können dazu führen, dass Objekte für unerwartet lange Zeit am Leben gehalten werden, wie z.B. die Verwendung mit bestimmten APIs.
Hinweise zu WeakRefs
- Wenn Ihr Code gerade eine
WeakRef
für ein Zielobjekt erstellt hat oder ein Zielobjekt aus derderef
-Methode einerWeakRef
erhalten hat, wird dieses Zielobjekt nicht vor dem Ende des aktuellen JavaScript-Auftrags (einschließlich aller Promise-Reaktionsjobs, die am Ende eines Skriptjobs ausgeführt werden) zurückgefordert. Das bedeutet, dass Sie ein Objekt nur zwischen den Schleifendurchläufen der Ereignisschleife wieder freigegeben sehen können. Dies dient in erster Linie dazu, das Verhalten des Garbage Collectors einer bestimmten JavaScript-Engine in Code nicht offenkundig zu machen — denn wäre es das, würden Leute Code schreiben, der von diesem Verhalten abhängt, was zu Problemen führen würde, wenn sich das Verhalten des Garbage Collectors ändert. (Speicherbereinigung ist ein schwieriges Problem; JavaScript-Engine-Implementierer verfeinern und verbessern kontinuierlich, wie sie funktioniert.) - Wenn mehrere
WeakRef
s dasselbe Ziel haben, sind sie untereinander konsistent. Das Ergebnis des Aufrufs vonderef
auf einer von ihnen entspricht dem Ergebnis des Aufrufs vonderef
auf einer anderen von ihnen (im gleichen Auftrag); Sie erhalten nicht das Zielobjekt von einer von ihnen, aberundefined
von einer anderen. - Wenn das Ziel einer
WeakRef
auch in einemFinalizationRegistry
ist, wird das Ziel derWeakRef
zur gleichen Zeit oder vor einem dazugehörigen Bereinigungs-Callback der Registry gelöscht; wenn Ihr Bereinigungs-Callbackderef
auf eineWeakRef
für das Objekt aufruft, erhält esundefined
. - Sie können das Ziel einer
WeakRef
nicht ändern, es wird immer nur das ursprüngliche Zielobjekt oderundefined
sein, wenn dieses Ziel zurückgefordert wurde. - Eine
WeakRef
könnte niemalsundefined
vonderef
zurückgeben, selbst wenn nichts das Ziel mehr stark hält, da der Garbage Collector möglicherweise nie entscheidet, das Objekt zurückzufordern.
Konstruktor
WeakRef()
-
Erstellt ein neues
WeakRef
-Objekt.
Instanzeigenschaften
Diese Eigenschaften sind auf WeakRef.prototype
definiert und werden von allen WeakRef
-Instanzen geteilt.
WeakRef.prototype.constructor
Optional-
Die Konstruktorfunktion, die das Instanzobjekt erstellt hat. Für
WeakRef
-Instanzen ist der Anfangswert derWeakRef
-Konstruktor.Hinweis: Diese Eigenschaft ist in der Spezifikation als "normativ optional" markiert, was bedeutet, dass eine konforme Implementierung die
constructor
-Eigenschaft möglicherweise nicht offenlegt. Dies verhindert, dass beliebiger Code denWeakRef
-Konstruktor erhält und die Speicherbereinigung beobachten kann. Alle großen Engines legen sie jedoch standardmäßig offen. WeakRef.prototype[Symbol.toStringTag]
-
Der anfängliche Wert der
[Symbol.toStringTag]
-Eigenschaft ist der String"WeakRef"
. Diese Eigenschaft wird inObject.prototype.toString()
verwendet.
Instanzmethoden
WeakRef.prototype.deref()
-
Gibt das Zielobjekt des
WeakRef
-Objekts zurück oderundefined
, wenn das Zielobjekt zurückgefordert wurde.
Beispiele
Verwendung eines WeakRef-Objekts
Dieses Beispiel startet einen Zähler, der in einem DOM-Element angezeigt wird und stoppt, wenn das Element nicht mehr existiert:
class Counter {
constructor(element) {
// Remember a weak reference to the DOM element
this.ref = new WeakRef(element);
this.start();
}
start() {
if (this.timer) {
return;
}
this.count = 0;
const tick = () => {
// Get the element from the weak reference, if it still exists
const element = this.ref.deref();
if (element) {
element.textContent = ++this.count;
} else {
// The element doesn't exist anymore
console.log("The element is gone.");
this.stop();
this.ref = null;
}
};
tick();
this.timer = setInterval(tick, 1000);
}
stop() {
if (this.timer) {
clearInterval(this.timer);
this.timer = 0;
}
}
}
const counter = new Counter(document.getElementById("counter"));
setTimeout(() => {
document.getElementById("counter").remove();
}, 5000);
Spezifikationen
Specification |
---|
ECMAScript® 2026 Language Specification # sec-weak-ref-objects |