Ist es möglich, eine „schwache Referenz“ in Javascript zu erstellen?

97

Gibt es in Javascript eine Möglichkeit, einen "schwachen Verweis" auf ein anderes Objekt zu erstellen? Hier ist die Wiki-Seite, die beschreibt, was eine schwache Referenz ist. Hier ist ein weiterer Artikel, der sie in Java beschreibt. Kann sich jemand eine Möglichkeit vorstellen, dieses Verhalten in Javascript zu implementieren?

Stephen Cagle
quelle
4
Für ES6 werden schwache Referenzen diskutiert. Halte deine Augen offen.
Ryan Smith
2
* Offizielles Spezifikations-Wiki / Diskussion unter wiki.ecmascript.org/doku.php?id=strawman:weak_refs , derzeit "Letzte Änderung: 2013/02/02 22:25" * Einige andere Spezifikationsdiskussion unter esdiscuss.org/topic/what -ist-der-Status-von-schwachen-Referenzen , derzeit letzter Beitrag "Sun Mar 3 11:56:05 PST 2013"
Destiny Architect
In den meisten Fällen sind WRs ein Versuch, das hier beschriebene Lapsed Listener-Problem zu lösen : [ stackoverflow.com/questions/43758217/… . Wenn diese Frage eine gute Antwort hätte, würde es meiner Meinung nach keinen großen Bedarf an WRs geben.
James
@supercat Ich habe eine Antwort auf die abgelaufene Hörerfrage gepostet .
James

Antworten:

39

Es gibt keine Sprachunterstützung für Schwachstellen in JavaScript. Sie können Ihre eigenen mit manueller Referenzzählung rollen, aber nicht besonders reibungslos. Sie können kein Proxy-Wrapper-Objekt erstellen, da Objekte in JavaScript nie wissen, wann sie im Müll gesammelt werden sollen.

So wird Ihre 'schwache Referenz' zu einem Schlüssel (z. B. einer Ganzzahl) in einer einfachen Suche mit einer Methode zum Hinzufügen und Entfernen von Referenzen. Wenn keine manuell verfolgten Referenzen mehr vorhanden sind, kann der Eintrag gelöscht werden, sodass zukünftige Suchvorgänge aktiviert bleiben dieser Schlüssel, um null zurückzugeben.

Dies ist nicht wirklich ein Schwachpunkt, aber es kann einige der gleichen Probleme lösen. Dies wird normalerweise in komplexen Webanwendungen durchgeführt, um Speicherverluste durch Browser (normalerweise IE, insbesondere ältere Versionen) zu verhindern, wenn eine Referenzschleife zwischen einem DOM-Knoten oder einer Ereignisbehandlungsroutine und einem damit verbundenen Objekt wie einem Abschluss besteht. In diesen Fällen ist möglicherweise nicht einmal ein vollständiges Referenzzählschema erforderlich.

Bobince
quelle
2
Ich habe den Code nicht sorgfältig untersucht (oder verwendet), aber es-lab verfügt über ein Skript, das eine grundlegende WeakMap-Emulation bietet . Aurora 6 (Mozilla) verfügt über eine nicht standardmäßige WeakMap-Implementierung .
Theazureshadow
2
Mit ES6 ist diese Antwort nicht mehr korrekt. Siehe meine Antwort unten stackoverflow.com/a/28567560/745190
thelastshadow
9
Es ist immer noch richtig, weil ES6 WeakMaps keine echten schwachen Referenzen sind. WeakMaps akzeptieren Objekte nur als Schlüssel, und die Verweise auf diese Objekte werden schwach gehalten. Siehe stackoverflow.com/questions/32397729/…
CodeManX
Ich habe eine Klasse geschrieben, um eine schwache Karte zu emulieren, und sie hier gepostet: stackoverflow.com/a/47017206/491553
Ryan Shillington
11

Update: September 2019

Es ist noch nicht möglich, schwache Referenzen zu verwenden, aber höchstwahrscheinlich wird es bald möglich sein, da WeakRefs in JavaScript in Arbeit sind. Details unten.

Vorschlag

Vorschlag jetzt in Phase 3, was bedeutet, dass es eine vollständige Spezifikation hat und dass eine weitere Verfeinerung Feedback von Implementierungen und Benutzern erfordert.

Der WeakRef- Vorschlag umfasst zwei wichtige neue Funktionen:

  • Erstellen schwacher Verweise auf Objekte mit der WeakRef-Klasse
  • Ausführen benutzerdefinierter Finalizer nach dem Sammeln von Objekten mit der FinalizationGroup-Klasse

Anwendungsfälle

Eine Hauptanwendung für schwache Referenzen ist das Implementieren von Caches oder Zuordnungen, die große Objekte enthalten, wobei gewünscht wird, dass ein großes Objekt nicht nur deshalb am Leben bleibt, weil es in einem Cache oder einer Zuordnung angezeigt wird.

Die Finalisierung ist die Ausführung von Code zur Bereinigung nach einem Objekt, das für die Programmausführung nicht mehr erreichbar ist. Benutzerdefinierte Finalizer ermöglichen mehrere neue Anwendungsfälle und können dazu beitragen, Speicherverluste bei der Verwaltung von Ressourcen zu vermeiden, von denen der Garbage Collector nichts weiß.

Quelle und weiterführende Literatur

https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references

M. Twarog
quelle
1
Firefox Nightly hat experimentelle Unterstützung für WeakRef hinzugefügt. Hier ist eine Beispielimplementierung, mit der eine iterierbare Version von WeakSet erstellt wird: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley
3

Echte schwache Referenzen, nein, noch nicht (aber Browserhersteller schauen sich das Thema an). Aber hier ist eine Idee, wie man schwache Referenzen simuliert.

Sie könnten einen Cache erstellen, durch den Sie Ihre Objekte fahren. Wenn ein Objekt gespeichert wird, sagt der Cache voraus, wie viel Speicher das Objekt belegen wird. Für einige Elemente, wie das Speichern von Bildern, ist dies einfach zu erarbeiten. Für andere wäre dies schwieriger.

Wenn Sie ein Objekt benötigen, fragen Sie den Cache danach. Wenn der Cache das Objekt enthält, wird es zurückgegeben. Wenn es nicht vorhanden ist, wird der Artikel generiert, gespeichert und dann zurückgegeben.

Die schwachen Referenzen werden durch das Entfernen von Elementen im Cache simuliert, wenn die Gesamtmenge des vorhergesagten Speichers ein bestimmtes Niveau erreicht. Es wird vorhergesagt, welche Elemente am wenigsten verwendet werden, basierend darauf, wie oft sie abgerufen werden, gewichtet nach der Zeit, vor der sie herausgenommen wurden. Es können auch Berechnungskosten hinzugefügt werden, wenn der Code, der das Element erstellt, als Abschluss in den Cache übergeben wird. Dies würde es dem Cache ermöglichen, Elemente zu behalten, deren Erstellung oder Generierung sehr teuer ist.

Der Löschalgorithmus ist der Schlüssel, denn wenn Sie dies falsch verstehen, können Sie am Ende die beliebtesten Elemente entfernen. Dies würde eine schreckliche Leistung verursachen.

Solange der Cache das einzige Objekt mit permanenten Verweisen auf die gespeicherten Objekte ist, sollte das obige System als Alternative zu echten schwachen Verweisen ziemlich gut funktionieren.

JL235
quelle
25
Ist das meiste, was Sie gesagt haben, für Schwachstellen nicht irrelevant?
Erik Kaplun
22
@ JL235 - Die wichtige Verwendung für schwache Referenzen ist nicht für Caches, sondern für Event-Handler. Ich habe ein Objekt, das, solange es existiert, ein anderes Ereignis beobachten sollte - aber ich möchte nicht, dass die Tatsache, dass es sich in einer Benachrichtigungsliste befindet, eine Referenz für die Zwecke der GC darstellt.
Malvolio
7
Schwache Referenzen haben nichts mit Caching zu tun. Eine schwache Referenz bedeutet, dass Sie etwas verfolgen möchten. Wenn jedoch keine Referenzen mehr auf das zu verfolgende Objekt vorhanden sind, können Sie es löschen.
Fabspro
8
Es gibt eindeutig einen Anwendungsfall zum Erstellen eines Caches unter Verwendung schwacher Referenzen für den automatischen Ablauf.
Phil Freeman
5
Caching ist traditionell der Hauptgrund für schwache Referenzen. Das Event-Handler-DOM-Ding ist nur ein IE-Explorer-Buggy.
Axkibe
2

Mit Hilfe eines Caching - Mechanismus einen schwachen Bezug zu emulieren, wie JL235 vorgeschlagen oben , ist vernünftig. Wenn schwache Referenzen nativ existieren würden, würden Sie ein Verhalten wie dieses beobachten:

this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not

Mit einem Cache würden Sie Folgendes beobachten:

this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts

Als Inhaber einer Referenz sollten Sie keine Annahmen darüber treffen, wann sie sich auf einen Wert bezieht. Dies ist bei Verwendung eines Caches nicht anders

Markus
quelle
-4

EcmaScript 6 (ES Harmony) verfügt über ein WeakMap- Objekt. Die Browserunterstützung unter modernen Browsern ist ziemlich gut (die letzten 3 Versionen von Firefox, Chrome und sogar eine kommende IE-Version unterstützen dies).

der letzte Schatten
quelle
29
Das ist nicht genau das gleiche. A WeakMapgibt keine schwachen Verweise auf Objekte an - es sind nicht die Werte , die schwache Verweise in WeakMap sind, sondern die Schlüssel . Die Tatsache, dass schwache Referenzen in der Karte vorhanden sind, ist nur ein Mechanismus zur Verhinderung von Speicherlecks und kann vom Benutzer ansonsten nicht beobachtet werden.
EyasSH
1
Sie haben Recht, dass die Schlüssel schwach sind, nicht die Werte. Der gesamte Zweck der Verwendung schwacher Referenzen besteht jedoch darin, die Speicherbereinigung des referenzierten Objekts zu ermöglichen. Das OP hat zwei Links veröffentlicht, von denen der zweite das Hinzufügen einer ID zu einem Objekt betrifft, das Sie nicht erweitern können. Tatsächlich empfiehlt es die Verwendung von WeakHashMap, dem Java-Äquivalent von JavaScript's WeakMap.
letzte Schatten
12
Glück WeakMap da einen schwachen Verweis zu implementieren Verwendung weakmap.get(new String('any possible key that has ever existed or ever will exist'))wird immer sein undefined. Nicht nützlich. Down-Voting!
user3338098
-5

http://www.jibbering.com/faq/faq_notes/closures.html

ECMAScript verwendet die automatische Speicherbereinigung. Die Spezifikation definiert die Details nicht und überlässt dies den Implementierern, um sie zu sortieren. Es ist bekannt, dass einige Implementierungen ihren Speicherbereinigungsvorgängen eine sehr niedrige Priorität einräumen. Die allgemeine Idee ist jedoch, dass ein Objekt, wenn es nicht mehr referenzierbar ist (da keine verbleibenden Verweise darauf für die Ausführung von Code verfügbar sind), für die Speicherbereinigung verfügbar wird und zu einem späteren Zeitpunkt zerstört wird und alle Ressourcen, die es verbraucht, freigegeben und zurückgegeben werden an das System zur Wiederverwendung.

Dies ist normalerweise beim Verlassen eines Ausführungskontexts der Fall. Die Bereichskettenstruktur, das Aktivierungs- / Variablenobjekt und alle im Ausführungskontext erstellten Objekte, einschließlich Funktionsobjekte, wären nicht mehr zugänglich und würden daher für die Speicherbereinigung verfügbar.

Das heißt, es gibt keine schwachen, nur solche, die nicht mehr verfügbar sind.

branchgabriel
quelle
10
Das Vermeiden von Referenzzyklen ist nicht der einzige Grund, schwache Referenzen zu verwenden. Sie sind sehr praktisch für das Pooling / Caching von Objektinstanzen und so weiter.
flauschig
Die Definition von WeakReference kommt nicht in Frage. Auch als mit Kommentar oben einverstanden.
Yuri Yaryshev