Lebensdauer von JavaScript-Objekten und Speicherlecks

8

Ich habe viel darüber recherchiert, aber hauptsächlich, indem ich andere Fragen zusammengefügt habe, was noch immer Zweifel aufkommen lässt. In einer App, die die Browserseite zu keinem Zeitpunkt aktualisiert und für einige Zeit (Stunden) ohne Schließen leben kann (vorausgesetzt, dass das Aktualisieren einer Seite oder das Navigieren zu einer anderen den JS-Code neu startet), ist der beste Weg zur Sicherstellung von Objekten freigegeben und es gibt keinen Speicherverlust.

Dies sind die spezifischen Szenarien, die mich interessieren:

Der gesamte folgende Code befindet sich in einem aufschlussreichen Modulmuster.

%Vor%

Variablen innerhalb von Funktionen, ich bin mir sicher, dass diese vom GC einfach gesammelt werden

%Vor%

Variablen innerhalb des Moduls, sollte g = null, wenn es nicht mehr benötigt wird?

%Vor%

Und schließlich das Leben eines jqXHR: Wird es nach der Rückkehr aufgeräumt? Sollte es vorsichtshalber in einer Funktion oder in einem Modul auf Null gesetzt werden?

Wenn dies geschieht, wird es nach der Rückkehr vom GC bereinigt?:

%Vor%

Wie wäre es damit, wird es auch bereinigt, nachdem x zurückkommt?:

%Vor%

Schließlich gibt es eine Möglichkeit, alle Variablen zu bereinigen und ein Modul neu zu starten, ohne den Browser neu zu starten?

    
Tony Basallo 13.11.2011, 21:24
quelle

6 Antworten

7
  

Variablen innerhalb von Funktionen, ich bin mir sicher, dass diese vom GC einfach gesammelt werden

Ja.

  

Variablen innerhalb des Moduls, sollte g = null, wenn es nicht mehr benötigt wird?

Sicher.

  

Und schließlich das Leben eines jqXHR: Wird es nach der Rückkehr aufgeräumt? Sollte es vorsichtshalber in einer Funktion oder in einem Modul auf Null gesetzt werden?

Verschiedene Browser hatten Fehler im Zusammenhang mit XHR, die dazu führten, dass onreadystatechange und alles, was geschlossen wurde, nicht einholbar waren, es sei denn, der Entwickler war vorsichtig, es durch einen Dummy-Wert zu ersetzen ( xhr.onreadystatechange = new Function('') ), aber ich glaube, dass jQuery dies für Sie erledigt .

  

Schließlich gibt es eine Möglichkeit, alle Variablen zu bereinigen und ein Modul neu zu starten, ohne den Browser neu zu starten?

Der mit der Seite verknüpfte globale Status nimmt den Browserspeicher auf, bis die Seite aus dem Browserprotokollstapel entfernt wird. location.replace kann Ihnen hier helfen, indem Sie die aktuelle Seite beenden und durch eine neue Version von die gleiche App, ohne den History-Stack zu erweitern.

  

Ersetzen Sie das aktuelle Dokument durch das unter der angegebenen URL. Der Unterschied zur Methode assign() besteht darin, dass nach der Verwendung von replace() die aktuelle Seite nicht im Sitzungsverlauf gespeichert wird, dh der Benutzer kann die Schaltfläche Zurück nicht verwenden, um dorthin zu navigieren.

Wenn Sie das Wort "Modul" verwenden, ist das kein Begriff, der eine wohldefinierte Bedeutung für den Browser oder seinen JavaScript-Interpreter hat, so dass es keine Möglichkeit gibt, ein Modul und nur ein Modul aus dem Speicher zu entfernen. Es gibt mehrere Dinge, über die Sie sich Gedanken machen müssen, die Dinge im Gedächtnis behalten könnten:

  1. Verweise auf JavaScript-Objekte, die an DOM-Knoten angehängt wurden und alles, was sie schließen - Event-Handler sind ein sehr häufiges Beispiel.
  2. Live setInterval und setTimeout Callbacks und alles, was sie schließen.
  3. Eigenschaften des globalen Objekts und alles, was sie schließen.
  4. Wie Sie bereits angemerkt haben, Eigenschaften bestimmter Host-Objekte wie XHR-Instanzen, Web-Worker-Callbacks usw. und (Sie haben es erraten) alles, was sie schließen.

Jedes Schema, das ein Modul entlädt und nur ein Modul, müsste sich mit all diesen befassen und herausfinden, welche von ihnen Teil des Moduls sind und welche nicht. Das sind viele verschiedene Arten von Aufräumarbeiten.

    
Mike Samuel 13.11.2011, 21:35
quelle
1

Javascript ist eine Müll-gesammelte Sprache. Es beruht auf dem Garbage Collector, um nicht verwendeten Speicher zu bereinigen. Im Wesentlichen müssen Sie darauf vertrauen, dass der GC seine Arbeit machen wird.

Der GC wird (eventuell nicht sofort) Objekte sammeln, die für Sie nicht erreichbar sind. Wenn Sie einen Verweis auf ein Objekt haben, wird es möglicherweise noch verwendet, und der GC wird es nicht berühren.

Wenn Sie weder direkt noch indirekt auf das Objekt verweisen, weiß der GC, dass das Objekt nicht verwendet werden kann und das Objekt erfasst werden kann. Alles, was Sie wirklich tun müssen, ist sicherzustellen, dass Sie alle Verweise auf das Objekt zurücksetzen.

Der GC gibt jedoch keine Garantie für , wenn das Objekt erfasst wird. Und darüber solltest du dir keine Sorgen machen.

    
jalf 13.11.2011 21:31
quelle
1

Wirklich die einzigen Lecks, um die Sie sich sorgen sollten, sind Schließungen.

%Vor%

Der GC hat keine Möglichkeit, var b zu löschen - er liegt außerhalb des Bereichs. Dies ist ein großes Problem mit IE, nicht so sehr mit Mozilla und noch weniger mit Chrome.

    
AlienWebguy 13.11.2011 21:35
quelle
1

Als Faustregel gilt, dass Sie bei jeder von Garbage Collection gesammelten Sprache (dies gilt z. B. für Java, .NET und JavaScript) sicherstellen möchten, dass kein verweilender Verweis auf einen gewünschten Speicherblock vorhanden ist den GC für dich aufräumen zu lassen. Wenn der GC einen Speicherblock betrachtet und feststellt, dass sich im Programm immer noch etwas befindet, wird darauf hingewiesen, dass es nicht freigegeben wird.

In Bezug auf den jqXHR ist es sinnlos, sie am Ende eines AJAX-Funktionsaufrufs auf null zu setzen. Alle Parameter eines AJAX success / error / complete werden freigegeben, sobald die Funktion vom GC zurückgegeben wird, es sei denn, jQuery macht etwas bizarres, wie einen Verweis auf sie zu behalten.

    
Mike Thomsen 13.11.2011 21:39
quelle
1

Jede Variable, auf die Sie nicht mehr zugreifen können, kann vom GC erfasst werden. Wenn Sie eine Variable innerhalb einer Funktion deklarieren, kann die Variable nach dem Beenden der Funktion entfernt werden. ist , wenn der Computer nicht mehr genügend Speicherplatz hat oder zu einem anderen Zeitpunkt.

Dies wird komplizierter, wenn Sie asynchrone Funktionen wie XHR ausführen. Die Schließungen done und fail können auf alle in den äußeren Funktionen deklarierten Variablen zugreifen. Solange also done und fail ausgeführt werden können, müssen alle Variablen im Speicher verbleiben. Sobald die Anfrage beendet ist, können die Variablen freigegeben werden.

Wie auch immer, Sie sollten einfach sicherstellen, dass jede Variable so tief wie möglich deklariert ist.

    
Yogu 13.11.2011 21:35
quelle
0

Ist das erste Beispiel mit 'g', sollte g auf Null gesetzt werden. Andernfalls wird der Zeiger auf "dd" beibehalten.

Im zweiten Beispiel muss das "x" im ersten Fall nicht auf null gesetzt werden, da diese Variable "verschwindet", wenn die umgebende Funktion beendet wird. Im zweiten Fall, mit 'x' außerhalb der Funktion, behält 'x', was auch immer ihm zugewiesen ist, und das wird nicht GC'd, bis 'x' auf null oder etwas anderes gesetzt ist.

    
Will Hartung 13.11.2011 21:35
quelle

Tags und Links