molily: Closures und Garbage Collection

Beitrag lesen

Falls die in Safari eingesetzte JS Engine hinreichend gut optimiert, tritt das beschriebene Problem erst gar nicht auf: Da in den inneren Funktionen kein eval() vorkommt, muss die Closure keine Referenz auf die komplette lexikale Umgebung der äußeren Funktion bereithalten, sondern nur Referenzen auf die tatsächlich benötigten Objekte.

Dazu müsste sie ja zur »Compile-Time« alle Identifier der inneren Funktion prüfen, ob darin Variablen sind, die nur in der äußeren Funktion notiert sind.

Das kann die Engine aber aus Prinzip nicht, sonst würde folgendes nicht funktionieren:

(function () {  
	var lokVar = "Hallo";  
	window.onload = function closure () {  
		alert(eval("lokVar"));  
	}  
})();

Das geht aber im JavaScriptCore/Squirelfish, was mich zur Annahme führt, dass tatsächlich das gesamte Variable Object gespeichert bleibt.

http://www.jibbering.com/faq/faq_notes/closures.html#clScCh sagt, dass das auch vorgeschrieben ist:

»Function objects created with function declarations or function expressions have the scope chain of the execution context in which they are created assigned to their internal [[scope]] property. (...) Inner function declarations and expressions result in function objects being created within the execution context of a function so they get more elaborate scope chains. (...) Variable instantiation for that new execution context results in the creation of a function object that corresponds with the inner function definition and the [[scope]] property of that function object is assigned the value of the scope from the execution context in which it was created.«

D.h. eine Closure hat folgende Scope Chain:

1. Activation/Variable Object der inneren Funktion
2. Activation/Variable Object der äußeren Funktion
3. Globales Objekt

Konsequenz daraus:
http://www.jibbering.com/faq/faq_notes/closures.html#clFrmC

»... the function object now referred to by globalVar was created with a [[scope]] property referring to a scope chain containing the Activation/Variable object belonging to the execution context in which it was created (and the global object). Now the Activation/Variable object -cannot be garbage collected [! --molily] either as the execution of the function object referred to by globalVar will need to add the whole scope chain [!] from its [[scope]] property to the scope of the execution context created for each call to it.«

Mathias