Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. JavaScript
  3. JavaScript-Referenz
  4. Eingebaute Standardobjekte
  5. FinalizationRegistry

Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.

View in EnglishAlways switch to English

FinalizationRegistry

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.

EinFinalizationRegistry-Objekt ermöglicht es Ihnen, einen Rückruf anzufordern, wenn ein Wert vom Garbage Collector eingesammelt wird.

Beschreibung

FinalizationRegistry bietet eine Möglichkeit, anzufordern, dass einBereinigungs-Rückruf zu einem bestimmten Zeitpunkt aufgerufen wird, wenn ein im Registry registrierter Wertzurückgewonnen (durch den Garbage Collector eingesammelt) wurde. (Bereinigungs-Rückrufe werden manchmalFinalisierer genannt.)

Hinweis:Bereinigungs-Rückrufe sollten nicht für wesentliche Programmlogik verwendet werden. SieheAnmerkungen zu Bereinigungs-Rückrufen für Details.

Sie erstellen die Registry, indem Sie den Rückruf übergeben:

js
const registry = new FinalizationRegistry((heldValue) => {  // …});

Dann registrieren Sie jeden Wert, für den Sie einen Bereinigungs-Rückruf wünschen, indem Sie die Methoderegister aufrufen und den Wert sowie einengehaltenen Wert dafür übergeben:

js
registry.register(target, "some value");

Die Registry hält keine starke Referenz auf den Wert, da dies den Zweck vereiteln würde (wenn die Registry ihn stark hielte, würde der Wert niemals zurückgewonnen werden). In JavaScript sind Objekte undnicht registrierte Symbole durch den Garbage Collector einsammelbar, daher können sie in einemFinalizationRegistry-Objekt als Ziel oder Token registriert werden.

Wenntarget zurückgewonnen wird, kann Ihr Bereinigungs-Rückruf zu einem bestimmten Zeitpunkt mit demgehaltenen Wert aufgerufen werden, den Sie dafür bereitgestellt haben („some value“ im obigen Beispiel). Der gehaltene Wert kann ein beliebiger Wert sein: ein primitiver Wert oder ein Objekt, sogarundefined. Wenn der gehaltene Wert ein Objekt ist, hält die Registry einestarke Referenz darauf (damit sie ihn später an Ihren Bereinigungs-Rückruf übergeben kann).

Falls Sie möglicherweise später einen registrierten Zielwert abmelden möchten, übergeben Sie einen dritten Wert, das sogenannteAbmeldetoken, das Sie später verwenden werden, wenn Sie die Funktionunregister der Registry aufrufen, um den Wert abzumelden. Die Registry hält nur eine schwache Referenz auf das Abmeldetoken.

Es ist üblich, den Zielwert selbst als Abmeldetoken zu verwenden, was völlig in Ordnung ist:

js
registry.register(target, "some value", target);// …// some time later, if you don't care about `target` anymore, unregister itregistry.unregister(target);

Es muss jedoch nicht derselbe Wert sein; es kann ein anderer sein:

js
registry.register(target, "some value", token);// …// some time laterregistry.unregister(token);

Vermeiden, wo möglich

Die korrekte Verwendung vonFinalizationRegistry 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 einer bestimmten 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 etwas anderen Situation mit derselben Version derselben Engine unterschiedlich sein. Die Speicherbereinigung ist ein schwieriges Problem, an dem Implementierer von JavaScript-Engines ständig arbeiten, um ihre Lösungen zu verfeinern und zu verbessern.

Hier sind einige spezielle Punkte, die von den Autoren imVorschlag aufgenommen wurden, derFinalizationRegistry eingeführt hat:

Garbage Collector sind kompliziert. Wenn eine Anwendung oder Bibliothek davon abhängig ist, dass die GC eineWeakRef rechtzeitig und vorhersehbar bereinigt oder einen Finalisierer [Bereinigungs-Rückruf] aufruft, wird sie wahrscheinlich enttäuscht: Die Bereinigung kann viel später geschehen als erwartet, oder überhaupt nicht. Quellen der Variabilität umfassen:

  • Ein Objekt könnte viel früher eingesammelt werden als ein anderes, selbst wenn sie gleichzeitig unerreichbar werden, z.B. aufgrund von Generationensammlung.
  • Die Arbeit der Speicherbereinigung kann über die Zeit hinweg mit inkrementellen und parallelen Techniken aufgeteilt 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 so aussehen, als wären sie unerreichbar (z.B. in Closures oder Inline-Caches).
  • Verschiedene JavaScript-Engines können diese Dinge unterschiedlich handhaben, oder dieselbe Engine kann ihre Algorithmen über Versionen hinweg ändern.
  • Komplexe Faktoren können dazu führen, dass Objekte für unerwartet lange Zeit erhalten bleiben, wie etwa die Verwendung mit bestimmten APIs.

Anmerkungen zu Bereinigungs-Rückrufen

  • Entwickler sollten sich nicht auf Bereinigungs-Rückrufe für wesentliche Programmlogik verlassen. Bereinigungs-Rückrufe können nützlich sein, um den Speicherverbrauch im Verlauf eines Programms zu reduzieren, sind aber ansonsten wahrscheinlich nicht nützlich.
  • Wenn Ihr Code gerade erst einen Wert in die Registry registriert hat, wird dieses Ziel nicht zurückgewonnen, bevor das Ende des aktuellen JavaScript-Jobs erreicht ist. SieheAnmerkungen zu WeakRefs für Details.
  • Eine konforme JavaScript-Implementierung, selbst eine mit Speicherbereinigung, ist nicht verpflichtet, Bereinigungs-Rückrufe aufzurufen. Wann und ob dies geschieht, liegt vollständig an der Implementierung der JavaScript-Engine. Wenn ein registriertes Objekt zurückgewonnen wird, können die Bereinigungs-Rückrufe dafür zu diesem Zeitpunkt, später oder gar nicht aufgerufen werden.
  • Es ist wahrscheinlich, dass große Implementierungen Bereinigungs-Rückrufe irgendwann während der Ausführung aufrufen, aber diese Aufrufe könnten erheblich nach dem Zeitpunkt erfolgen, zu dem das damit verbundene Objekt zurückgewonnen wurde. Außerdem, wenn ein Objekt in zwei Registries registriert ist, gibt es keine Garantie, dass die beiden Rückrufe nebeneinander aufgerufen werden - einer kann aufgerufen werden und der andere nie, oder der andere kann viel später aufgerufen werden.
  • Es gibt auch Situationen, in denen selbst Implementierungen, die normalerweise Bereinigungs-Rückrufe aufrufen, dies wahrscheinlich nicht tun:
    • Wenn das JavaScript-Programm vollständig herunterfährt (zum Beispiel das Schließen eines Tabs im Browser).
    • Wenn dieFinalizationRegistry-Instanz selbst nicht mehr durch JavaScript-Code erreichbar ist.
  • Wenn das Ziel einerWeakRef auch in einerFinalizationRegistry ist, wird das Ziel derWeakRef gleichzeitig oder vor einem mit dem Registry assoziierten Bereinigungs-Rückruf gelöscht; wenn Ihr Bereinigungs-Rückrufderef auf einerWeakRef für das Objekt aufruft, erhält erundefined.

Konstruktor

FinalizationRegistry()

Erstellt ein neuesFinalizationRegistry-Objekt.

Instanzeigenschaften

Diese Eigenschaften sind aufFinalizationRegistry.prototype definiert und werden von allenFinalizationRegistry-Instanzen gemeinsam genutzt.

FinalizationRegistry.prototype.constructor

Die Konstrukturfunktion, die das Instanzobjekt erstellt hat. BeiFinalizationRegistry-Instanzen ist der Ausgangswert derFinalizationRegistry-Konstruktor.

FinalizationRegistry.prototype[Symbol.toStringTag]

Der Anfangswert der[Symbol.toStringTag]-Eigenschaft ist der String"FinalizationRegistry". Diese Eigenschaft wird inObject.prototype.toString() verwendet.

Instanzmethoden

FinalizationRegistry.prototype.register()

Registriert ein Objekt bei der Registry, um einen Bereinigungs-Rückruf zu erhalten, wenn das Objekt durch den Garbage Collector eingesammelt wird.

FinalizationRegistry.prototype.unregister()

Meldet ein Objekt von der Registry ab.

Beispiele

Erstellen einer neuen Registry

Sie erstellen die Registry, indem Sie den Rückruf übergeben:

js
const registry = new FinalizationRegistry((heldValue) => {  // …});

Objekte für die Bereinigung registrieren

Dann registrieren Sie alle Objekte, für die Sie einen Bereinigungs-Rückruf wünschen, indem Sie die Methoderegister aufrufen und das Objekt sowie einengehaltenen Wert dafür übergeben:

js
registry.register(theObject, "some value");

Rückrufe werden niemals synchron aufgerufen

Unabhängig davon, wie viel Druck Sie auf den Garbage Collector ausüben, wird der Bereinigungs-Rückruf niemals synchron aufgerufen. Das Objekt kann synchron zurückgewonnen werden, aber der Rückruf wird immer irgendwann nach Abschluss des aktuellen Jobs aufgerufen:

js
let counter = 0;const registry = new FinalizationRegistry(() => {  console.log(`Array gets garbage collected at ${counter}`);});registry.register(["foo"]);(function allocateMemory() {  // Allocate 50000 functions — a lot of memory!  Array.from({ length: 50000 }, () => () => {});  if (counter > 5000) return;  counter++;  allocateMemory();})();console.log("Main job ends");// Logs:// Main job ends// Array gets garbage collected at 5001

Wenn Sie jedoch zwischen jeder Zuteilung eine kleine Pause zulassen, kann der Rückruf eventuell früher aufgerufen werden:

js
let arrayCollected = false;let counter = 0;const registry = new FinalizationRegistry(() => {  console.log(`Array gets garbage collected at ${counter}`);  arrayCollected = true;});registry.register(["foo"]);(function allocateMemory() {  // Allocate 50000 functions — a lot of memory!  Array.from({ length: 50000 }, () => () => {});  if (counter > 5000 || arrayCollected) return;  counter++;  // Use setTimeout to make each allocateMemory a different job  setTimeout(allocateMemory);})();console.log("Main job ends");

Es gibt keine Garantie dafür, dass der Rückruf früher aufgerufen wird oder überhaupt aufgerufen wird, aber es besteht die Möglichkeit, dass die geloggte Nachricht einen Zählerwert hat, der kleiner als 5000 ist.

Spezifikationen

Specification
ECMAScript® 2026 Language Specification
# sec-finalization-registry-objects

Browser-Kompatibilität

Siehe auch

Help improve MDN

Learn how to contribute Diese Seite wurde automatisch aus dem Englischen übersetzt.

[8]ページ先頭

©2009-2025 Movatter.jp