15.2 JavaScript Debugger  
Unter http://www.mozilla.org/projects/venkman/ stellt das Mozilla-Projekt einen kostenlosen Debugger für JavaScript-Programme zur Verfügung. Dieser bietet die Basiseigenschaften eines Debuggers, also das Setzen von Breakpoints und die Anzeige aktueller Variablenwerte während der Ausführung (dazu jeweils später mehr). Nach der Installation integriert sich der Debugger in das Menü des Browsers und kann per Extras N JavaScript Debugger gestartet werden.
 Hier klicken, um das Bild zu Vergrößern
Abbildung 15.2 Der Bildschirm nach dem Starten des Debuggers
15.2.1 Wo ist der Fehler?  
Nun benötigen wir noch ein fehlerhaftes Programm. Kaufen Sie also ein Konkurrenzwerk (war nur ein Scherz), oder werfen Sie einen Blick auf das folgende kurze Programm:
<html>
<head>
<title>Debugger</title>
<script type="text/javascript"><!--
var summe = 0;
var zaehler = 0;
var obergrenze;
function ungerade() {
zaehler++;
var summe = summe + zaehler;
if (zaehler < obergrenze) {
gerade();
}
}
function gerade() {
zaehler++;
var summe = summe + zaehler;
if (zaehler<obergrenze) {
ungerade();
}
}
function sum(n) {
obergrenze = n;
ungerade();
return summe;
}
//--></script>
</head>
<body>
<script type="text/javascript"><!--
document.write(sum(100));
//--></script>
</body>
</html>
Das Prinzip des obigen Programms ist relativ einfach. Die Hauptfunktion ist sum(n), die die Summe der Zahlen von 1 bis n berechnet. Um das Ganze ein wenig komplizierter (und damit fehlerträchtiger) zu machen, gehen wir wie folgt vor: In der globalen Variable summe wird das aktuelle Zwischenergebnis gespeichert, und in der globalen Variable zaehler merkt sich das Programm, welche Zahlen bis jetzt schon aufsummiert worden sind. Zunächst wird die Funktion ungerade() aufgerufen, die zunächst den Zähler um 1 erhöht (beim ersten Aufruf: auf 1) und dann den Wert des Zählers zur Zwischensumme addiert. Danach wird die Funktion gerade() aufgerufen, die genau dasselbe erledigt: zunächst Zähler erhöhen (beim ersten Aufruf: auf 2) und dann den Zählerwert zur Zwischensumme hinzuzählen. Sobald der Zähler die Obergrenze erreicht hat, wird abgebrochen.
Wenn man der Legende Glauben schenkt, hat Gauß schon im Grundschulalter diese Aufgabe gelöst. Sein Lehrer wollte ihn ein wenig beschäftigen und bat ihn, die Zahlen von 1 bis 100 zu addieren. Der kleine Gauß hat eine Weile überlegt und herausgefunden, dass man die Summe der Zahlen von 1 bis n mit der Formel n(n+1) berechnen kann; bei n=100 kommt 5050 heraus.
Wenn Sie das Skript im Browser aufrufen (starten Sie vorher unbedingt den Debugger, wie oben beschrieben!), werden Sie jedoch erstaunt feststellen, dass als Ergebnis 0 angezeigt wird. Woran kann das liegen?
Der Debugger weiß hier vielleicht Rat. Starten Sie den Debugger, so Sie im oberen Bereich unter anderem die (absichtlich) fehlerhafte Datei entdecken. Klicken Sie doppelt auf den Dateinamen, und der Quellcode erscheint (falls nicht, wählen Sie die Menüoption View N Show/Hide N Source Code).
 Hier klicken, um das Bild zu Vergrößern
Abbildung 15.3 Der Quellcode im Debugger
15.2.2 Breakpoints  
Um den Debugger wirklich nutzen zu können, müssen Sie einen so genannten Breakpoint setzen. Die wörtliche Übersetzung, »Unterbrechungspunkt« oder auch »Haltepunkt«, kommt der Wahrheit schon sehr nahe. Sobald der JavaScript-Interpreter beim Haltepunkt angekommen ist, wird die Skriptausführung unterbrochen und Sie können beispielsweise auf den aktuellen Wert aller Variablen zugreifen.
Breakpoints beziehen sich immer auf eine Zeile; die Programmausführung wird unterbrochen, bevor der Code in der Zeile ausgeführt wird. Prinzipiell gibt es zwei Möglichkeiten, einen Breakpoint zu setzen:
|
Klicken Sie in die entsprechende Zeile, und wählen Sie im Kontextmenü (rechte Maustaste) den Eintrag Set Breakpoint. |
|
Klicken Sie in der entsprechenden Zeile in den dunkelgrauen Bereich am linken Rand. |
Egal welche der beiden Methoden Sie einsetzen, Sie sehen danach eine rote Markierung im linken Rand, wodurch das Vorhandensein eines Breakpoints angedeutet wird.
In diesem Beispiel sollten Sie den Breakpoint in die Zeile zaehler++ der Funktion ungerade() setzen. Tun Sie das, und laden Sie im Browserfenster das (fehlerhafte) Skript erneut. Nach kurzer Zeit kommt das Debugger-Fenster in den Vordergrund; die aktuelle Position der Skriptausführung ist durch eine gelbe Hintergrundmarkierung gekennzeichnet.
15.2.3 Watches  
 Hier klicken, um das Bild zu Vergrößern
Abbildung 15.4 Watches werden in der Konsole angezeigt.
Es ist nun an der Zeit, die Werte einiger Variablen zu betrachten. Unter View N Show/Hide N Watches können Sie das Fenster für so genannte Watches einblenden, falls das noch nicht geschehen ist. Watches sind Variablen oder Ausdrücke, deren Wert Sie permanent überwachen möchten. Im Kontextmenü der Watches-Anzeige finden Sie den Eintrag Add Watch Expression, mit dem Sie eine neue Watch angeben können. Es empfiehlt sich in diesem Beispiel, ein genaueres Augenmerk auf die Variablen summe und zaehler zu werfen. Erstellen Sie also zwei Watches – eine für die Variable summe und eine für die Variable zaehler (alternativ können Sie auch im Fenster Locale Variables einen Wert auf alle lokalen Variablen werfen). Im Watches-Fenster werden die Variablennamen dann angezeigt, nebst allen zugehörigen Werten. Sobald sich der Wert einer der Variablen ändert, wird der neue Wert in der Konsole angezeigt. Sie müssen eigentlich nur noch das Programm weiterlaufen lassen (Schaltfläche Continue) und dabei zusehen, was geschieht.
 15.2.4 Schrittweise Programmausführung  
Sie sehen in der Symbolleiste ganz rechts fünf Schaltflächen, mit denen Sie die Skriptausführung wieder in Gang setzen können. Der Reihe nach haben diese die folgenden Funktionen:
|
Stop: Die Skriptausführung wird angehalten. |
|
Continue: Das Programm wird weiter ausgeführt, bis es entweder am Ende ankommt oder wieder bei einem Breakpoint stehen bleiben muss. |
|
Step Over: Es wird zur nächsten Zeile in der aktuellen Funktion gesprungen. Sollte der Interpreter am Ende der Funktion angelangt sein, verhält sich die Schaltfläche wie Run. |
|
Step Into: Es wird zur nächsten Zeile des Programmcodes gesprungen, ganz egal, ob diese innerhalb der aktuellen Funktion liegt oder außerhalb. |
|
Step Out: Die aktuelle Funktion wird verlassen und das Programm weiter ausgeführt, bis es endet oder am nächsten Breakpoint stehen bleiben muss. |
|
Profile: Es wird ein so genanntes Profiling des Skripts durchgeführt: Welcher Teil dauert wie lange? |
|
Pretty Print: Quellcode wird »hübsch« formatiert. |
Beachten Sie nun genau, was geschieht, wenn Sie von der Zeile zaehler++ aus mit Step Into weiter vorgehen. Anfangs hat zaehler einen Wert von 0 und summe einen Wert von void. Nach der Ausführung des Kommandos zaehler++ hat zaehler den Wert 1, der Wert von summe hat sich nicht geändert. In der nächsten Zeile jedoch ändert sich der Wert von summe – aber nicht wie erhofft in 1, sondern in ... NaN, not a number. Warum nur?
Mit ein wenig Überlegung ist klar, wo der Fehler liegt. Vor der Anweisung summe = summe + zaehler steht ein var. Dadurch wird summe innerhalb der Funktion ungerade() – und analog dazu auch in gerade() – zu einer lokalen Variablen, deren Wert außerhalb der Funktion nicht sichtbar ist. Die Variable summe ist aber eigentlich als globale Variable konzipiert.
 Hier klicken, um das Bild zu Vergrößern
Abbildung 15.5 Die Variable summe hat offensichtlich einen falschen Wert.
Entfernen Sie sowohl in der Funktion ungerade() als auch in der Funktion gerade() das Schlüsselwort var vor summe, brechen Sie im Debugger die Skriptausführung ab, und laden Sie die Seite im Browser neu. Ein Blick in den Debugger verheißt Gutes, denn nun wird summe anständig erhöht. Und wenn Sie nun noch den Breakpoint entfernen (zweimal in den dunkelgrauen Bereich klicken) und das Skript durchlaufen lassen, sehen Sie im Browser auch das korrekte Ergebnis – 5050. Wir haben zwar etwas länger gebraucht als der kleine Gauß, aber dafür durften wir ja auch nicht per Hand rechnen.
|