JavaScript/Tutorials/Grundlagen/Debuggen

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Informationen zu diesem Text

Lesedauer
45min
Schwierigkeitsgrad
mittel
Vorausgesetztes Wissen
Grundkenntnisse in JavaScript

Programmieren beinhaltet immer auch die Suche nach Fehlern. Neben Syntaxfehlern existieren auch logische Fehler. In JavaScript erzeugen Fehler oft keinen Abbruch oder eine Fehlermeldung und sorgen erst viel später für Probleme, deren Ursache dann durch Debuggen herausgefunden werden muss.

In diesem Tutorial lernen Sie, wie Sie Scripte auf Programmierfehler überprüfen und debuggen können. Als wichtiges Entwicklungswerkzeug, das die JavaScript-Programmierung entscheidend erleichtert, verwenden wir die eingebaute Konsole.

Damit können Sie ...

und

bisherige Vorgehensweise[Bearbeiten]

In einem ersten Schritt können Sie zum Testen einfach Blöcke auskommentieren und so Schritt für Schritt überprüfen, welche Zeilen/ Blöcke im Code nicht funktionieren.

Mit Hilfe von window.alert können Sie eine Kontrollausgabe von Variablen und den ihnen zugewiesenen Werten vornehmen. Wurde ein alert ausgeführt, wusste man, dass der Code bis dahin funktionierte. Nachteile dieser Methode waren, dass ein alert das Programm anhielt und erst nach einer Bestätigung des Nutzers weiterlaufen ließ. Mehrere alerts überlasteten schnell den Speicher.

Eventuell ist der Fehler nicht in dieser Zeile, sondern schon in einer der vorhergehenden zu finden. Versuchen Sie nachzuvollziehen, warum es in dieser Zeile zu dem Fehler kommt.

Weiterhin können Sie während des Entwickelns mit try ... catch Fehler ermitteln und als Fehlermeldung ausgeben.

Heutzutage können diese Fehlersuchen bequem durch die browsereigene Konsole durchgeführt werden.

Kontrollausgabe mit der Konsole[Bearbeiten]

Die Konsole öffnen[Bearbeiten]

Die Konsole öffnet sich unterschiedlich, je nach Browser. Das kann zum einen über die jeweiligen Menüs, über die Funktionstaste F12, oder aber durch eine der folgenden Tastenkombinationen geöffnet werden:

  • Mozilla Firefox: unter Windows und Linux mit Strg + Umschalt + I, unter Mac mit Cmd + Opt + I
  • Google Chrome: unter Windows und Linux mit Strg + Umschalt + J, unter Mac mit Cmd + Opt + J
  • Microsoft Edge und Internet Explorer: F12 anschließend Strg + 2

Screenshot

(Ansicht der Firebug-Konsole im Firefox Version 40)

Debuggen mit Haltepunkten[Bearbeiten]

Durch die oben aufgeführten Kontrollausgaben können Sie den Ablauf eines Scriptes nachvollziehen und Variablen ausgeben, um deren Werte zu prüfen. Selbst minifizierter Code kann wieder lesbar formatiert werden.

Ist Ihnen rechts neben der Konsole der Debugger (Überwachen) aufgefallen? Er ist ein vielseitiges und mächtiges Werkzeug, mit dem Sie die Funktionsweise eines Scriptes komfortabler untersuchen können, denn Sie müssen nicht nach jeder Anweisung eine Kontrollausgabe einfügen. Ein JavaScript-Debugger bietet im Allgemeinen folgende Möglichkeiten:

Setzen von Haltepunkten[Bearbeiten]

Sie können Haltepunkte (englisch Breakpoints) setzen, indem sie in der Konsole im Quelltext erst oben links auf das Symbol klicken und dann die einzelnen Zeilennummern markieren. Die Ausführung des JavaScripts wird an dieser Stelle unterbrochen und Sie können alle Variablen und Objekte rechts im Debugger sehen und überprüfen.

Screenshot

Mit einem Klick auf den aktuellen Haltepunkt, der nun ein Play-Symbol beinhaltet, können Sie das Script von dieser Code-Zeile aus wieder zum Laufen bringen und die folgenden Anweisungen nun Schritt für Schritt ausführen, Anweisungen überspringen und aus aufgerufenen Funktionen herausspringen. Bei dieser schrittweisen Ausführung können Sie überprüfen, welche Werte bestimmte Objekte und Variablen an dieser Stelle im Script haben.


Call Stack[Bearbeiten]

Bei komplerexen Programmen mit mehreren Funktionen, die sich gegenseitig aufrufen, hilft Ihnen ein Debugger, die Übersicht über das Aufrufen und Abarbeiten von Funktionen zu behalten. In der Einzelschritt-Ausführung haben Sie den sogenannten Call Stack (englisch für Aufruf-Stapel) im Blick. Das ist die Verschachtelung der Funktionen, die gerade abgearbeitet werden. Wenn beispeilsweise die Funktion a die Funktion b aufruft und diese wiederum die Funktion c, so ist der Stapel a > b > c. Die Funktion c, die gerade ausgeführt wird, liegt sozusagen oben auf dem Stapel. Nach dessen Ausführung wird c vom Stapel genommen und in die Funktion b zurückgekehrt - und so weiter.

Fallen und Fehlerquellen[Bearbeiten]

runde oder geschweifte Klammern[Bearbeiten]

Alle Klammern die geöffnet werden, müssen auch wieder geschlossen werden!
Ist eine Klammer zuviel im Script-Code?

Hochkommata um Strings[Bearbeiten]

Fehlt ein schließendes Hochkomma oder wird ein doppeltes Hochkomma durch ein einfaches Hochkomma geschlossen?

Bindestrich im Variablennamen?[Bearbeiten]

Wenn Sie eine Variable mit einem Bindestrich schreiben, wird aus ihrem Namen eine Zuweisung, da JavaScript den Bindestrich als Rechenoperator ansieht und versucht die beiden Teile der Variablen zu substrahieren.

Groß- und Kleinschreibung[Bearbeiten]

Javascript ist case-sensitive, dass heißt, das nameVorname und namevorname unterschiedliche Variablen sind. Sie geben in der Konsole im strengen Modus eine Fehlermeldung.

Empfehlung: Verwenden Sie das so genannte CamelCase, in dem jeweils der erste Buchstabe der einzelnen Bestandteile des Namens groß geschrieben wird.
Beispiel:
DiesIstEineVariable.

Schreibfehler in einer der DOM-Methoden? Vor allem Methoden wie getElementById werden oft falsch geschrieben. Hier hilft ein Web-Editor mit autocomplete, der Methoden und mehrmals verwendete Variablen automatisch vorschlägt.

oktale Syntax[Bearbeiten]

Besonders im Bereich der Datumsberechnung werden häufig Zahlen mit führender Null benutzt. Einfache Aufgaben wie alert(08 * 60) liefern dann scheinbar falsche Ergebnisse oder gar Fehlermeldungen.

Des Rätsels Lösung dafür ist, dass JavaScript Zahlen mit führender 0 als Oktalzahlen interpretiert, nicht als Dezimalzahlen. Die Notation von Oktalzahlen mit einer führenden Null ist eine in vielen Programmiersprachen verbreitete Konvention, die ursprünglich von C kommt.

Mit einer Anweisung wie parseInt("08", 10) können Sie das Problem vermeiden und erzwingen, dass der Wert dezimal interpretiert wird.

Empfehlung: Verwenden Sie den strict mode, um die Interpretation als Oktalzahlen auszuschließen.

Siehe auch[Bearbeiten]


Quellen[Bearbeiten]


ToDo (weitere ToDos)

Ist Ihnen aufgefallen, dass alle Beispiel in diesem Artikel funktionieren?

Besser wäre es, die Methoden der Console API in einen eigenen Artikel auszulagern und stattdessen fehlerhafte Skripte vorzustellen, die der Leser selbst debuggen muss.


>> Der Programmierer meinte wenn man statt eines . ein , verwendet dann führt das zu einem Javascript Fehler.

Nein, nicht unbedingt. Es führt aber zu einem völlig anderem Ergebnis:

1,414 + 1,732 ergibt: 732. Was passiert, ist:

   Werte den Ausdruck vor dem ersten , aus: 1.
   Werte den nächsten Ausdruck aus: 414 + 1 ergibt 415.
   Werte den nächsten Ausdruck aus: 732.
   Der zurückgegebene Wert ist der letzte, also 732.

Hingegen: 1.414 + 1.732 ergibt 3.146.

Beispiel
var a = 23;
var b = 42;
if (a = b) {
  alert('23 ist 42, q.e.d.');
}

Oft sind es die kleinen Fehler, die man übersieht, auch wenn man sich den Code dreimal anschaut. Zumindest könnte man mit einem console.log(a) vor der if-Abfrage bemerken, dass der Inhalt von a noch stimmt, innerhalb dann aber den Inhalt von b angenommen hat, was nicht beabsichtigt war. Und so muss der Fehler zwischen den beiden console.log() sitzen.

Beispiel
var a = 23;
var b = 42;
console.log(a, b);
if (a = b) {
  console.log(a, b);
  alert('23 ist 42, q.e.d.');
}

Self-Forum: Wiki: Tutorial Grundlagen von Strings und Arrays vom 20.04.2017

--Matthias Scharwies (Diskussion) 06:28, 21. Apr. 2017 (CEST)

klare Programmstruktur und Kommentare =[Bearbeiten]

Im Übrigen macht eine klare Programmstruktur die Fehlersuche deutlich einfacher. Das heißt, es gilt monolithische Konstruktionen zu vermeiden und statt dessen die verschiedenen Aufgaben auf relativ kurze und gut überschaubare Funktionen zu verteilen, wobei dann auch nicht mit Kommentaren gespart werden sollte.

Rumprobieren[Bearbeiten]

ToDo (weitere ToDos)

Rumprobieren ist in der Regel allerdings nicht die effizienteste Methode um Fehlerursachen zu identifizieren. Das heißt, wann immer irgendwas nicht funktioniert, sollte zunächst ein Blick auf die Konsole deines Browsers geworfen werden:

Wenn dein Programm mit einem Fehler abgebrochen hat, findest du dort entsprechende Hinweise, also um welche Art von Fehler es sich handelt, wie zum Beispiel …

  • ein Syntax Error, etwa wenn das Schließen einer Klammer vergessen wurde, oder
  • ein Reference Error, wenn du an einer Stelle versuchst über einen Bezeichner eine Variable zu referenzieren, die in dem jeweiligen Kontext (noch) nicht existiert (also wie mit event in deinem Frageposting), oder
  • ein Type Error, üblicherweise dadurch verursacht, dass an einer Stelle ein Objekt erwartet wird, aber statt dessen der primitive Wert undefined vorliegt, da die Übergabe vergessen wurde (siehe newElement in deinem Frageposting)

… sowie darüber hinaus auch immer eine Angabe dazu gegeben wird, an welcher Stelle, also in welcher Datei und in welcher Zeile der Fehler aufgetreten ist. Meistens genügt das schon, um den Fehler zu finden.

Manchmal funktioniert etwas aber auch nicht, ohne dass das Programm durch eine Ausnahme beendet wurde. In diesem Fall hilft die Eingrenzungstaktik, wobei man step by step diejenigen Teile des Programms ausschließt, die funktionieren wie gewünscht, bis dann schließlich der Teil gefunden ist, der nicht funktioniert. Dabei kann dann das debugger Statement hilfreich sein:

(function test (value) {
  'use strict';
  debugger;
  value = 'bar';
  debugger;
  value = 'baz';
  debugger;
}('foo'));

Wenn du deine Seite dann im Browser ausführst und bei den Entwicklertools den Debugger aufrufst, dann wird das Programm bei jedem Auftreten von debugger angehalten und es werden dir unter anderem die Werte der Variablen zu diesem Zeitpunkt angezeigt.

Hier im Beispiel würde das Programm also gleich nach Eintritt in die Funktion angehalten und du könntest sehen, dass die lokale Variable (Parameter) value den Wert foo hat. Wenn du nun im Debugger auf fortsetzen (oder so ähnlich) klickst, dann läuft das Programm bis zum nächsten debugger und hält dann wieder an, sodass du wieder die aktuellen Werte überprüfen kannst.

Das heißt, wenn das Script des Beispiels hier fortgesetzt wird, dann ist der nächste Stop nach der ersten Wertzuweisung und du könntest sehen, dass die Variable nunmehr den Wert bar hat, usw.

Davon abgesehen besteht natürlich auch immer die Möglichkeit, sich mittels der verschiedenen Methoden der console-Schnittstelle bestimmte Werte explizit anzeigen zu lassen. Dann ist entsprechend immer zu prüfen, ob die tatsächlichen Werte an einer Stelle mit den erwarteten Werten übereinstimmen. So kommt man der Fehlerursache Schritt für Schritt näher. ;-)

Weblinks[Bearbeiten]