Die Konsole kann mehr als nur log
console.log ist das erste Debugging-Werkzeug, das die meisten in JavaScript lernen – und für viele bleibt es bis zum Schluss das einzige. Funktioniert ja auch. Trotzdem: Das console-Objekt bringt ein gutes Dutzend weiterer Methoden mit, die dich beim Debuggen schneller und klarer ans Ziel bringen. Und sobald du dich in den Chrome DevTools wirklich zu Hause fühlst – mit Breakpoints, Call Stack und Watch Expressions – wirst du automatisch seltener zu log greifen.
Verschaffen wir uns zunächst einen kurzen Überblick:
Alle vier schreiben in dieselbe Konsole, aber die Browser stellen sie unterschiedlich dar: Warnungen bekommen einen gelben Hintergrund, Fehler werden rot hervorgehoben und mit einem Icon versehen, und beide liefern einen Stacktrace mit. Über die Filter in den DevTools lassen sich die einzelnen Level ausblenden oder isoliert anzeigen – das wird spätestens dann wichtig, wenn deine App hunderte Meldungen pro Minute produziert.
Mehrere Werte ausgeben – der bequeme Weg
Wenn du mehrere Variablen gleichzeitig sehen willst, bau sie bloß nicht per String-Konkatenation zusammen. Übergib sie stattdessen als einzelne Argumente – oder noch besser: pack sie in ein Objekt, dann ist jeder Wert automatisch beschriftet:
Der Trick mit { user, count } nutzt die Object-Shorthand-Syntax: Der Variablenname wird automatisch zum Key. In der Konsole siehst du dann { user: {...}, count: 3 } und kannst user aufklappen, um reinzuschauen. Im Gegensatz zum Stringifyen bleibt die Struktur des Objekts dabei vollständig erhalten.
console.table für Arrays von Objekten
Wenn du ein Array von Objekten vor dir hast, spuckt console.log nur ein zusammengeklapptes Chaos aus. console.table macht daraus eine echte Tabelle:
In der Browser-Konsole zeigt der erste Aufruf alle drei Zeilen mit sortierbaren Spalten an. Der zweite Aufruf beschränkt die Ausgabe auf name und role. Für alles, was datenförmig ist – API-Antworten, Query-Ergebnisse, eingelesene CSV-Dateien – ist das ein riesiger Komfortgewinn.
console.dir vs. console.log
Auf den ersten Blick wirken beide identisch, bei DOM-Elementen verhalten sie sich aber unterschiedlich:
const el = document.querySelector("button");
console.log(el); // gibt das HTML aus: <button>Click me</button>
console.dir(el); // gibt die JS-Objektansicht mit allen Eigenschaften aus
log stellt Elemente als HTML dar. dir hingegen zeigt dir das reine Objekt – mit allen Eigenschaften, Event-Handlern und Verweisen auf berechnete Styles. Wenn du wissen willst, welche Methoden oder Attribute ein Element tatsächlich hat, ist dir dein Freund.
Zusammengehörige Logs gruppieren
Bei längeren Debug-Sessions geht in der Konsole schnell die Übersicht verloren. Mit console.group und console.groupEnd packst du zusammengehörige Ausgaben in einen einklappbaren Block:
Jeder Aufruf erzeugt eine benannte Gruppe, die du einklappen kannst. Wenn du möchtest, dass Gruppen standardmäßig zugeklappt starten, nimm console.groupCollapsed – praktisch, wenn du nur die verdächtigen Einträge aufklappen willst.
Performance messen mit console.time
Für schnelle Performance-Checks sind console.time und console.timeEnd kaum zu schlagen:
Das Label in time und timeEnd muss übereinstimmen. Du kannst auch mehrere Timer mit verschiedenen Labels parallel laufen lassen. Für alles, was über "ist diese Schleife lahm?" hinausgeht, wechselst du besser ins Performance-Panel der DevTools – dort bekommst du eine komplette Timeline samt Flame-Chart.
Assertions: nur loggen, wenn wirklich was schiefläuft
console.assert gibt nur dann etwas aus, wenn die Bedingung falsy ist. So kannst du Sanity-Checks dezent im Code lassen, ohne die Konsole vollzuspammen, solange alles passt:
Gut für Invarianten, die immer gelten sollten. Schlecht dagegen für Dinge, die legitim fehlschlagen können — dafür gehört ein echter Error geworfen.
Stacktrace auf Zuruf
console.trace gibt den aktuellen Call Stack aus, ohne etwas zu werfen. Praktisch, wenn du rausfinden willst, wer eine Funktion überhaupt aufgerufen hat:
Die Ausgabe lautet inner → outer → (top level). In einer echten Anwendung findest du so heraus, dass der Click-Handler, den du debuggst, tatsächlich von drei verschiedenen Stellen aus ausgelöst wird.
Das debugger-Statement
Am schnellsten pausierst du die JavaScript-Ausführung mit einem einzigen Wort:
function computeTotal(items) {
const subtotal = items.reduce((s, i) => s + i.price, 0);
debugger;
return subtotal * 1.08;
}
Wenn die DevTools geöffnet sind, wirkt debugger; wie ein echter Breakpoint — die Ausführung hält genau an dieser Zeile an, und du bekommst den vollen Debugger: alle Variablen im aktuellen Scope, den Call Stack, Step-Over- und Step-Into-Buttons und die Möglichkeit, beliebige Ausdrücke im aktuellen Zustand auszuwerten. Sind die DevTools geschlossen, passiert bei debugger; schlicht nichts.
Das erste Mal einen richtigen Debugger statt console.log zu benutzen fühlt sich an wie ein Cheatcode. Du siehst jede Variable im Scope, ohne vorher zu entscheiden, was du ausgeben willst. Du kannst Schritt für Schritt durch Verzweigungen gehen und genau sehen, welcher Zweig ausgeführt wird. Kniffelige Bugs zu fixen dauert plötzlich Sekunden statt Minuten.
Die debugger-Zeile solltest du vor dem Commit wieder rausnehmen — oder noch besser: setze Breakpoints direkt in den DevTools, indem du im Sources-Panel auf eine Zeilennummer klickst.
DevTools-Tricks, die du kennen solltest
Ein paar Features, die viele jahrelang übersehen:
- Conditional Breakpoints: Im Sources-Panel mit Rechtsklick auf eine Zeilennummer eine Bedingung wie
user.id === 42setzen. Der Breakpoint greift nur, wenn die Bedingung erfüllt ist. - Logpoints: dasselbe Menü, "Add logpoint." Schreibt eine Meldung in die Konsole, ohne zu pausieren und ohne dass du deinen Code anfassen musst.
$_in der Konsole: das Ergebnis des zuletzt ausgewerteten Ausdrucks. Etwas ausführen, dann mit$_wieder draufzugreifen.$0: das aktuell im Elements-Panel markierte Element.$0.textContentzeigt dir den Textinhalt von dem, was du angeklickt hast.- Copy as object: Rechtsklick auf einen beliebigen Wert in der Konsole und "Store as global variable." auswählen. Du bekommst dann
temp1,temp2usw. zum Rumprobieren. - Network-Panel → Copy as fetch: macht aus jedem Request einen
fetch()-Aufruf, den du in die Konsole einfügen und anpassen kannst.
Nichts davon ist lebensnotwendig. Aber sobald das alles in der Fingermuskulatur sitzt, sparst du jede Menge Zeit.
Aufräumen, bevor es in Produktion geht
Übrig gebliebene console.log-Aufrufe sind in der Entwicklung harmlos, in Produktion aber nur lästiges Rauschen. Ein paar Gewohnheiten, die helfen:
- Eine Lint-Regel einsetzen (
no-consolein ESLint), um herumliegende Logs zu markieren — mit Ausnahmen fürwarnunderror. - Ausführliches Logging in eine Abfrage packen:
if (process.env.NODE_ENV !== "production") console.log(...). - Für Trace-Ausgaben lieber
console.debugverwenden — die meisten Bundler und Log-Aggregatoren können das wegfiltern. - Noch besser: ein kleines Logger-Modul (oder eine Library wie
debug) nutzen, damit sich ganze Log-Kategorien ein- und ausschalten lassen, ohne den Code anzufassen.
Logging ist nicht kostenlos. Jeder Aufruf serialisiert seine Argumente und schreibt in einen Buffer. In einer heißen Schleife kann ein vergessenes Log spürbar Performance kosten.
Als Nächstes: Reguläre Ausdrücke
Beim Debuggen geht es oft um Code, der Strings verarbeitet — und der steckt häufig voller Regex, dem kompaktesten und gleichzeitig kryptischsten Feature der Sprache. Im nächsten Kapitel gibt es eine entspannte Tour durch reguläre Ausdrücke in JavaScript und die Methoden, die sie nutzen.
Häufig gestellte Fragen
Was ist der Unterschied zwischen console.log und console.dir?
console.log gibt Werte in der Standarddarstellung des Browsers aus – bei DOM-Elementen heißt das: du siehst das gerenderte HTML. console.dir zeigt dagegen immer die JavaScript-Objektansicht mit allen Properties. Genau das willst du, wenn du nicht das Markup, sondern die Eigenschaften eines Elements inspizieren möchtest.
Wie debugge ich JavaScript in den Chrome DevTools ohne console.log?
Öffne das Sources-Panel, such deine Datei und klick auf eine Zeilennummer, um einen Breakpoint zu setzen. Sobald die Ausführung an dieser Stelle ankommt, pausiert sie – du kannst Variablen inspizieren, Schritt für Schritt durch den Code gehen und Ausdrücke direkt in der Console auswerten. Alternativ kannst du ein debugger;-Statement in den Code schreiben, um den Breakpoint aus dem Quellcode heraus auszulösen.
Wie messe ich, wie lange JavaScript-Code zum Ausführen braucht?
Pack den Code zwischen console.time('label') und console.timeEnd('label') – wichtig ist, dass beide Labels übereinstimmen. Die Console gibt dir dann die verstrichene Zeit in Millisekunden aus. Für detailliertere Analysen nimmst du das Performance-Panel in den DevTools und zeichnest einen Flame Chart von allem auf, was gelaufen ist.
Wofür ist console.table gut?
console.table rendert Arrays und Objekte als sortierbare Tabelle in der Console – deutlich übersichtlicher als ein verschachtelter Object-Dump. Besonders praktisch bei Arrays von Objekten: jedes Objekt wird zu einer Zeile, die Keys werden zu Spalten. Mit einem zweiten Argument kannst du außerdem einschränken, welche Spalten angezeigt werden.