Hallo,
ich baue gerade eine Web-App für den Mobile Safari, bei der alle Daten mit Ajax nachgeladen werden. D.h. ein und dasselbe Dokument bleibt sehr lange geöffnet. Ich habe zwar noch keine Anzeichen von vollgelaufenen Speicher, aber ich mache mir Gedanken darum, ob der Garbage Collector die ständig angelegten und über siebenunzwanzig Callbacks herumgereichten Objekte irgendwann korrekt löscht.
Dazu habe ich Closures (verschachtelte Funktionen) soweit es geht vermieden, sodass Variablen möglichst nicht eingeschlossen und konserviert werden. Dummerweise weiß ich nicht, wie ich so etwas kontrollieren kann. Ich dachte, man könne Variablen mit delete aus der Welt schaffen, aber das geht gerade bei mit »var« deklarierten lokalen Variablen nicht (ist so in ECMAScript definiert - ich rall es einfach nicht):
function bla () {
var lokal = {}; // Soll nicht eingeschlossen werden
var enclosed = {}; // Soll eingeschlossen werden
weitereFunc(lokal, enclosed);
$('#bla').click(function closure () {
alert(enclosed);
});
// Versuche ich zu vermeiden z.B. mit Kontrolliertem Anlegen von Closures via Currying
// Legt aber auch jedes Mal Funktionen an. Wenn die beim Löschen der Elemente bzw. der Handler nicht weggeräumt werden, dann läuft der Speicher irgendwann voll
$('#bla').click( externerHandler.curry(enclosed) );
delete lokal; // geht nicht per definitionem
lokal = undefined; // Objekt händisch löschen - löscht aber nur diese eine Referenz darauf
}
Problem ist nun, dass ich viele »weitereFunc« habe, die allesamt das Object by Reference übergeben bekommen. Theoretisch müsste »lokal« nach Ablauf dieser Funktionen gelöscht werden, wenn diese keine Closure beinhalten. Allerdings ist das JS mittlerweile so groß, dass ich das gerne automatisiert testen würde. Ich weiß aber nicht, wie ich Einblick in den Stack des JS-Interpreters gewinnen kann. Ich vermute, dass lokal = undefined nur die lokale Variable überschreibt, aber wenn das Object noch woanders eingeschlossen ist, existieren weitere Referenzen darauf und der GC übersieht es.
Ein schwerwiegenderes Problem scheinen mir Referenzen auf DOM-Objekte, die in Closures eingeschlossen werden. Das DOM wird ja ständig geändert, sodass der GC alte, ausgehängte DOM-Objekte löschen müsste. Tut er das aber z.B. wegen Closures nicht, dürfte der Speicher meiner Ansicht nach schnell volllaufen. Das kann ich wie gesagt noch nicht beobachten (auf dem Desktop-Safari), aber ich würde es gerne prüfen können.
Habt ihr dazu Ideen?
Mathias