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.
Ein WeakRef
-Objekt ermöglicht es Ihnen, eine schwache Referenz zu einem anderen Objekt zu halten, ohne zu verhindern, dass dieses Objekt durch den Garbage Collector entfernt wird.
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 es dem Garbage Collector erlaubt, das Objekt zurückzufordern. 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 des JavaScript-Engines das Objekt zerstören und seinen Speicher freigeben. Wenn das passiert, können Sie das Objekt nicht mehr aus einer schwachen Referenz abrufen.
Da nicht registrierte Symbole ebenfalls vom Garbage Collector gesammelt werden können, können sie auch als Ziel eines WeakRef
-Objekts verwendet werden. Allerdings ist der Anwendungsfall dafür begrenzt.
Verzichten Sie nach Möglichkeit darauf
Der korrekte Einsatz von WeakRef
erfordert sorgfältiges Überlegen und sollte vermieden werden, wenn möglich. Es ist auch wichtig, sich nicht auf irgendein bestimmtes Verhalten zu verlassen, das nicht durch die Spezifikation garantiert wird. Wann, wie und ob eine Garbage Collection erfolgt, hängt von der Implementierung eines bestimmten JavaScript-Engines ab. Jedes beobachtbare Verhalten in einem Engine kann in einem anderen Engine, in einer anderen Version desselben Engines oder sogar in einer etwas anderen Situation mit derselben Version desselben Engines unterschiedlich sein. Die Garbage Collection ist ein schwieriges Problem, zu dessen Lösung die Entwickler von JavaScript-Engines ständig ihre Lösungen verfeinern und verbessern.
Hier sind einige spezifische Punkte, die von den Autoren im Vorschlag aufgenommen wurden, der WeakRef
eingeführt hat:
Garbage Collector sind kompliziert. Wenn eine Anwendung oder Bibliothek darauf angewiesen ist, dass der GC eine
WeakRef
in einer zeitnahen, vorhersehbaren Weise bereinigt oder einen Finalizer [Bereinigung-Callback] aufruft, wird sie wahrscheinlich enttäuscht sein: Die Bereinigung kann viel später stattfinden als erwartet oder gar nicht. Variabilitätsquellen sind unter anderem:
- Ein Objekt könnte viel früher als ein anderes Objekt durch den Garbage Collector eingesammelt werden, selbst wenn sie gleichzeitig nicht mehr erreichbar sind, z.B. aufgrund von Generationen-Sammlung.
- Die Arbeit der Garbage Collection kann über die Zeit mit inkrementellen und parallelen Techniken aufgeteilt werden.
- Verschiedene Laufzeitheuristiken können genutzt werden, um Speicherverbrauch und Reaktionsfähigkeit auszubalancieren.
- Der JavaScript-Engine kann Referenzen zu Dingen halten, die nicht erreichbar erscheinen (z.B. in Closures oder Inline-Caches).
- Verschiedene JavaScript-Engines können diese Dinge unterschiedlich handhaben, oder derselbe Engine kann seine Algorithmen über Versionen hinweg ändern.
- Komplexe Faktoren können dazu führen, dass Objekte unerwartet lange am Leben gehalten werden, wie z.B. die Nutzung mit bestimmten APIs.
Hinweise zu WeakRefs
- Wenn Ihr Code gerade eine
WeakRef
für ein Zielobjekt erstellt oder das Zielobjekt von derderef
-Methode einerWeakRef
erhalten hat, wird dieses Zielobjekt nicht vor dem Ende des aktuellen JavaScript-Jobs (einschließlich aller Promise-Reaktionsjobs, die am Ende eines Skript-Jobs ausgeführt werden) zurückgefordert. Das bedeutet, Sie können nur „sehen“, dass ein Objekt zwischen den Durchläufen der Ereignisschleife zurückgefordert wird. Dies soll hauptsächlich vermeiden, dass das Verhalten des Garbage Collectors eines bestimmten JavaScript-Engines im Code sichtbar wird — denn wenn dies der Fall wäre, würden Entwickler Code schreiben, der von diesem Verhalten abhängig ist, was brechen würde, wenn sich das Verhalten des Garbage Collectors ändern würde. (Die Garbage Collection ist ein schwieriges Problem; JavaScript-Engine-Implementierer verfeinern und verbessern ständig, wie sie funktioniert.) - Wenn mehrere
WeakRef
s dasselbe Ziel haben, sind sie konsistent miteinander. Das Ergebnis des Aufrufs vonderef
bei einem von ihnen stimmt mit dem Ergebnis des Aufrufs vonderef
bei einem anderen von ihnen überein (im selben Job), Sie erhalten das Zielobjekt nicht von einem von ihnen, aberundefined
von einem anderen. - Wenn das Ziel einer
WeakRef
auch in einemFinalizationRegistry
ist, wird das Ziel derWeakRef
gleichzeitig oder bevor ein Bereinigungs-Callback aufgerufen wird, das mit dem Register verbunden ist, gelöscht; wenn Ihr Bereinigungs-Callbackderef
bei einerWeakRef
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
kann möglicherweise nieundefined
vonderef
zurückgeben, selbst wenn nichts das Ziel stark hält, weil der Garbage Collector möglicherweise nie entscheidet, das Objekt zurückzufordern.
Konstruktor
WeakRef()
-
Erstellt ein neues
WeakRef
-Objekt.
Instanz-Eigenschaften
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" gekennzeichnet, was bedeutet, dass eine konforme Implementierung die
constructor
-Eigenschaft möglicherweise nicht bereitstellt. Dies verhindert, dass beliebiger Code denWeakRef
-Konstruktor erhält und die Garbage Collection beobachten kann. Alle großen Engines stellen sie jedoch standardmäßig bereit. WeakRef.prototype[Symbol.toStringTag]
-
Der Anfangswert der
[Symbol.toStringTag]
Eigenschaft ist der String"WeakRef"
. Diese Eigenschaft wird inObject.prototype.toString()
verwendet.
Instanz-Methoden
WeakRef.prototype.deref()
-
Gibt das Zielobjekt des
WeakRef
-Objekts zurück oderundefined
, wenn das Zielobjekt zurückgefordert wurde.
Beispiele
Verwenden 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 Language Specification # sec-weak-ref-objects |
Browser-Kompatibilität
BCD tables only load in the browser