eval

Programmierung von Javascript-Anweisungen

Die Funktion eval ermöglicht es, Javascript-Befehle variabel zu programmieren. Dazu werden an Stelle der Variablen, Funktionen, Objekte und Methoden deren Namen verwendet. Alle modernen Programmiersprachen bieten die Funktion eval oder ein Äquivalent.
Diese Funktion ist wenig bekannt, erlaubt jedoch in speziellen Fällen eine sehr elegante "Programmierung des Programms".
Javascript ECMAScript für HTML und XML
eval Syntax
Variablen-Namen Befehle auf verschiedene Variable anwenden
Objekt-Namen Befehle für verschiedene Objekte, Methoden, Eigenschaften anwenden
Funktions-Namen Verschiedene Funktionen anwenden
JSON Zuweisung empfangener Daten an Arrays oder Objekte
DOM Nach Möglichkeit besser das Document Object Model verwenden
Verwandte Themen eval in PHP

eval zur "Programmierung eines Programms"

Wie funktioniert eval ?

Die Funktion eval erhält als Argument einen Text (String).
Dieser Text muss eine Javascript-Anweisung (oder einen Teil davon) als Quelltext enthalten.
eval führt diesen Befehlstext aus - genauso als ob der gleiche Text als Quelltext in einem Javascript-Programm stehen würde.

Die Umwandlung von Quelltext und sofortige Ausführung wird in der Informatik mit "Interpretation" bezeichnet. Die Anweisung eval arbeitet sozusagen als Interpreter für Javascript.

Wozu soll das gut sein ?

eval ist eine sehr spezielle Methode, die in den meisten Programmen nicht gebraucht wird.
Einige spezielle Probleme lassen sich allerdings nur mit eval lösen.
Die Funktionsweise von eval ist anfangs nicht leicht zu durchschauen. Die Beispiele dieser Seite sollten dabei helfen.
Tipp: Alle modernen Programmiersprachen enthalten eine prinzipiell gleich arbeitende Funktion eval

Einfaches Demo-Beispiel

Die Funktion eval benötigt als Argument einen Text (String). Der Text muss genau einer Javascript-Anweisung entsprechen, und zwar bis zum abschließenden ; Zeichen.
Mit eval wird die als Text übergebene Anweisung ausgeführt.

Die vierte Variante zeigt, wie mit eval nur ein Teil eines Befehls ausgeführt wird - In diesem Fall die "Berechnung" des Variablen-Namens a

Diese vier Varianten einer Javascript-Anweisung sind äquivalent:
a = 123;
eval("a=123;");
anweisung = "a=123;";
eval(anweisung);
eval("a") = 123;
In dieser einfachen Form ist die Anwendung von eval natürlich sinnlos - Man verwendet besser den Befehl selbst (Variante der ersten Zeile) als eval mit einem Text des Befehls.
eval ist kein Taschenrechner !
Der Vorteil besteht in der Möglichkeit, in einem Programm einen beliebigen Anweisungs-Text zusammenzusetzen und danach auszuführen.
Das ist die einzige Möglichkeit, die Namen von Variablen Objekten, Methoden, Eigenschaften, ... variabel zu programmieren.
Es erfordert einige Übung, mit eval fehlerfrei zu programmieren.
Tipp: Stellen sie den Befehls-Text zuerst in einer Variablen (hier t ) zusammen und kontrollieren sie vor und nach der Ausführung.
Wenn alles funktioniert, löschen sie die alert-Zeilen.
t = "a=234;";
alert("Anweisung = "+t);
eval(t);
alert("Ergebnis:\n a="+a);
Es gibt eine wesentliche Einschränkung:
eval arbeitet vergleichsweise langsam !
eval sollte daher nur dann verwendet werden, wenn es keine andere Möglichkeit der (eleganten) Programmierung gibt.

Programmierung von Variablen-Namen

Mit eval ist es möglich, die Namen von Variablen, Arrays, Objekten ... zu programmieren.

Die Demo-Funktion trace zeigt den momentanen Wert einer beliebigen Variablen an. Der Name der gewünschten Variablen wird als String übergeben.

Im Anwendungs-Beispiel wird mit Funktion trace verfolgt, wie sich der Wert von Variablen (hier x und y ) im Laufe des Programms ändert.
Anwendung auf beliebige Variable:
function trace(vn) {
alert(vn+"="+eval(vn));
}
// Anwendung:
var x=123;   var y=0;
trace("x");  trace("y");
for(i=0;i<5;i++) {
x++;   y=2*x;
}
trace("x");  trace("y");
Ohne eval könnte die Funktion nur eine bestimmte Variable anzeigen, mit eval jedoch jede beliebige Variable. Vorsicht: In dieser einfachen Version kann trace nur globale Variable verfolgen (d.h. keine Variablen von Unterprogrammen) !

Programmierung von Objekt-Namen, -Methoden, -Eigenschaften

Namen von Objekten

Das gezeigte <form> Element enthält ungewöhnlich viele Eingabe-Felder. Das trifft u.a. dann zu, wenn eine Webseite so ähnlich wie ein Kalkulations-Programm funktionieren soll.
Ein Sudoku enthält z.B. 9*9=81 Eingabe-Felder.
Ziel: Nach jeder Änderung soll der aktuelle Wert aller 81 Felder in einem Javascript-Programm gelesen werden.
<form name="f1">
<input type="text" name="feld1">
<input type="text" name="feld2">
<!-- ... -->
<input type="text" name="feld81">
</form>
Ohne eval muss der Werte jedes einzelnen Felds mit einem eigenen Befehl gelesen werden. (Die anschließende Verarbeitung ist zur Vereinfachung weggelassen).
Viele ähnliche Programmzeilen sind normalerweise ein sicheres Indiz für die Auslagerung in ein Unterprogramm. An Stelle vieler ähnlicher Befehle wird ein Unterprogramm mehrfach ausgeführt.
Wenn jedoch nicht die Daten sondern (wie hier) die Namen von Variablen oder Objekten variabel sind, ist das nicht möglich.
eval bietet eine elegante Möglichkeit, dieses Problem zu lösen.
Das Beispiel zeigt, wie die Namen (feld1, feld2, ..) als Text formuliert, in einen Befehlstext eingebaut und an eval zur Ausführung übergeben werden.
Ohne eval:
w = document.f1.feld1.value;
w = document.f1.feld2.value;
// ..weitere 78 Zeilen
w = document.f1.feld81.value;

Mit eval:
for(i=1;i<=81;i++) {
t = "w=document.f1.";
t+="feld"+i+".value;";
eval(t);
}
Diese Methode bringt umso mehr Vorteile, je mehr gleichartige oder ähnliche Objekte zu bearbeiten sind. Alternative: Versehen sie jedes zu verwendende HTML-Element mit einem id-Attribut und verwenden sie DOM-Methoden (Kapitel auf dieser Seite).

Namen von Methoden oder Eigenschaften

Mit eval können auch die Namen verschiedener Methoden variabel programmiert werden. Das Beispiel zeigt zuerst die einzelne Anwendung der Methoden play und stop

Mit eval lässt sich die angewendete Methode programmieren, z.B. m="play"; oder m="stop";

Als Sicherheits-Maßnahme wird der Befehl innerhalb eines try-Blocks ausgeführt: Wenn nicht existierende sound-Objekte oder unzulässige Methoden auftreten, wird der Befehl einfach ignoriert.
Ohne eval: Methoden sind fix im Quellcode eingetragen
s = "sound1";
document.embeds[s].play();
document.embeds[s].stop();

Mit eval: Methoden sind variabel programmierbar
s = "sound1";
m = "play";
t = "document.embeds["+s+"]."+m+"();"
try {eval(t);}
catch(e) {}

Eigenschaften

Die große Zahl der CSS-Eigenschaften lässt sich mit eval variabel programmieren.
Im Beispiel wird ein HTML-Element mit Hilfe seines id-Attributs identifiziert.
Danach werden seine CSS-Eigenschaften height und width gelesen - zuerst fix, danach mit eval variabel programmiert.

Details zu Objekten, Eigenschaften & Methoden.
Details zu CSS, zur Adressierung von DOM-Elementen und zur Programmierung des style-Objekts mit Javascript.
HTML:
<span id="test">Muster</span>
Ohne eval: Eigenschaften sind fix im Quellcode eingetragen
n = document.getElementById("test");
w = n.style.height;
w = n.style.width;
Mit eval: Eigenschaften sind variabel programmierbar
n = document.getElementById("test");
p = "height";
eval("w=n.style."+p+";");
cssp = "width";
eval("w=n.style."+p+";");

Anwendung variabler Funktionen

Mit eval ist es möglich, je nach Bedarf unterschiedliche Funktionen auszuführen.

Das Beispiel ist sowohl auf Standard Javascript-Funktionen als auch auf eigene Funktionen (hier add und sub) anwendbar.
Das Konzept kann beliebig ausgeweitet werden: Durch Änderung des Befehls-Textes, können andere Variable oder eine andere Anzahl von Variablen eingesetzt werden, usw.
Ohne eval ist die verwendete Funktion fix im Quelltext eingetragen:
r = add(a,b);
r = sub(a,b);
Mit eval sind Funktions-Namen (und die Namen der Variablen) programmierbar:
f = "add";
eval("r="+f+"(a,b);");
f = "sub";
eval("r="+f+"(a,b);");

Zuweisung JSON-formatierter Daten

Funktion eval wird häufig im Zusammenhang mit Ajax (Empfang von Daten und Objekten durch Javascript) verwendet.
Ein Ajax-Server formatiert die angebotenen Daten und Objekte als Liste von Elementen, getrennt durch , Beistrich. Texte werden in "" eingeschlossen. (Beispiel rechts oben).
Beim Empfang der Daten durch Javascript werden die Daten zunächst als Text an eine Variable (hier atxt) zugewiesen.
Danach werden die Daten mit eval an ein Array (hier ar) übergeben. Durch die Interpretation wird aus jedem Element der Text-Liste ein Element des Javascript-Arrays.
Das Array wird anschließend verarbeitet, je nach Aufgabe des Programms.
Beispiel JSON-formatierter Daten:
12,34,"Rita","Stefan",789

Empfang der vom Ajax-Server erhaltenen Daten:
var atxt = ajax_obj.responseText;

Umwandlung in JSON-Syntax:
atxt = "["+atxt+"]";

Interpretation mit eval:
var ar = eval(atxt);

Anwendung:
alert(ar[2]);
ergibt Rita
Dieses Verfahren hat viele Vorteile:
Die Liste kann beliebig viele Elemente enthalten.
Die Elemente können gemischt Zahlen und/oder Text enthalten.
Auf ähnliche Weise werden auch Objekte inklusive ihrer Eigenschaften und Methoden JSON-codiert, übertragen und mit eval decodiert.

Details zu den Themen Ajax, Array, JSON, Objekt

Ersatz von eval durch DOM-Methoden

In manchen Fällen kann eval durch Anwendung von DOM-Methoden ersetzt werden.

Das Document Object Model (DOM) ist das grundlegende Konzept zur Verwaltung hierarchischer Objekte wie z.B. einer Webseite und aller darin enthaltener Elemente.
Ein bestimmtes Element (hier: eine von vielen Zellen einer Tabelle) wird meist mit seinem id-Attribut adressiert, welches eindeutig sein muss.

DOM-Methoden sind im Zweifel immer vorzuziehen: Sie arbeiten meist wesentlich schneller und sind zukunftssicher - Sie arbeiten mit allen Mitgliedern der XML-Familie, insbesondere auch mit XHTML.

Das Beispiel rechts zeigt, wie man den aktuellen Wert aus den Zellen einer Tabelle mit DOM-Methoden lesen und schreiben (hier abgeschaltet) kann.

Das id-Attribut wird als Text verwendet und lässt sich daher bequem in einer Schleife programmieren.

Details zur Verwendung von DOM-Methoden mit Javascript.
HTML-Tabelle:
<table>
<tr>
<td id="z1">123</td>
<td id="z2">234</td>
</tr>
<tr>
<td id="z3">345</td>
<td id="z4">456</td>
</tr>
<!-- weitere Zeilen... -->
</table>

Javascript mit DOM (einzeln)
n = document.getElementById("z1");
w = n.firstChild.nodeValue;
// n.firstChild.Value=987.toString();
Das gleiche Beispiel in einer Schleife für 100 Zellen
for(i=1;i<100;i++) {
id = "z"+i.toString();
n = document.getElementById(id);
w = n.firstChild.nodeValue;
//n.firstChild.Value=987.toString();
}