molily: Dynamisch erzeugte Handler-Funktionen - ohne eval()

Beitrag lesen

Hallo,

var arg1 = "Hallo";

eval("elem.onclick = function() {test('" + arg1 + "');}");


> Sieht zwar nicht so schön aus, aber funktioniert unter IE, Firefox und Opera perfekt :-)  
  
Sieht tatsächlich nicht schön aus, so solltest du nicht vorgehen. eval() ist sehr langsam, fehlerträchtig und darüber hinaus schlechter Programmierstil, Code im Code dynamisch zusammenzusetzen.  
  
eval() ist eigentlich immer unnötig und die schlechtere der möglichen Alternativen, es gibt viele bessere Methoden.  
  
  
Wenn du unbedingt JavaScript-Code als String notieren willst, kannst du so eine Funktion notieren:  
  
~~~javascript
var handler = new Function("test(" + arg + ")");  
elem.onclick = handler;

Siehe Defining functions.

Das hat aber immer noch einige Nachteile, schließlich wird dabei auch so eine Art eval() durchgeführt.

Eine bessere, vielseitigere und einfachere Methode ist es, die im Handler benötigten Variablen als Eigenschaften am Elementobjekt zu speichern.

elem.arg1 = "Hallo";  
elem.onclick = handler;  
  
function handler () {  
   alert(this.arg1);  
}

Noch einmal zurück zu deinem eval-Code:

var arg1 = "Hallo";  
eval("elem.onclick = function() {test('" + arg1 + "');}");

Bei diesem minimalen Beispiel ist eval() überhaupt nicht nötig. Wenn du folgendes schreibst,

var arg1 = "Hallo";  
elem.onclick = function () {  
   alert(arg1);  
};

wirst du dich wundern, dass arg1 in der Funktion verfügbar ist (auch wenn arg1 keine globale Variable ist). Denn die Funktion wirkt hier als Closure. (Diesen Artikel solltest du dir ohnehin anschauen, siehe auch Möglichkeiten der Datenspeicherung)

Closures sind die zweite vielseitige Möglichkeit, um Objekte bzw. Variablen in Event-Handler-Funktionen zur Verfügung zu stellen, die dort sonst nicht zur Verfügung stünden.

Es gibt also zusammengefasst folgende Alternativen:

  • Die Daten als Eigenschaften am Elementobjekt speichern, wo der Event passiert bzw. durch Event-Bubbling vorbeikommt und behandelt wird. Auf diese Daten kann man im Handler einfach über this.eigenschaft zugreifen.
  • Die Daten durch Closures in den Handler-Funktionen verfügbar machen, sofern möglich.
  • Wenn die anderen beiden Methoden nicht zum Ziel führen: Dynamisch Funktionen erzeugen, indem man deren Funktionskörper als String erzeugt und new Function() verwendet.

Mathias

--
»No nations, no borders.«
SELFHTML Weblog