Learn JavaScript - Debugging and Console Tools
Episode 19 of 23

Learn JavaScript - Debugging and Console Tools

This episode equips you with the ability to find and fix bugs: the Console API for observation, the debugger statement and breakpoints for inspecting execution, reading errors and stack traces, and using DevTools to analyze network and performance.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

Writing code is only half the job — the other half is finding out why code doesn't do what you want. Episode 19 turns you from a code writer into a debugger: someone who can read symptoms, find root causes, and fix them quickly.

The good news: modern browsers already provide very complete debugging tools through DevTools. What's often missing isn't the tools but the technique. This episode covers that technique: using the Console API strategically, inspecting execution with breakpoints, reading errors and stack traces, then analyzing network requests and performance.

One mindset shift matters: console.log isn't the only tool, and isn't always the best. You'll see when console.table beats console.log, and when breakpoints are far more powerful than printing values.

The Console API for Observation

Log, Warn, and Error

The Console API provides different levels for different messages, and DevTools colors them so they're easy to scan:

JSConsole message levels
console.log("Informasi normal");
console.warn("Peringatan, ini mencurigakan");
console.error("Kesalahan fatal yang perlu diselidiki");

console.warn and console.error show messages with different icons and colors. This isn't just aesthetics: the console can also be filtered by level, so separating info, warnings, and errors helps you find the problem among thousands of messages.

table for Structured Data

For lists of objects, console.table displays a table that's far easier to read than raw objects:

JSconsole.table for an array of objects
const tim = [
  { nama: "Arman", role: "Backend" },
  { nama: "Sari", role: "Frontend" },
  { nama: "Budi", role: "DevOps" },
];
 
console.table(tim);

console.table(tim) displays an array of objects as a table with the nama and role columns. Spotting an anomaly in ten rows of table data is far faster than digging through nested objects in the console. This is the first tool to reach for when data looks wrong.

group and time for Structure and Duration

console.group groups messages, and console.time measures execution duration:

JSgroup and time
console.time("proses-data");
 
console.group("Mulai pemrosesan");
console.log("Langkah 1 selesai");
console.log("Langkah 2 selesai");
console.groupEnd();
 
console.timeEnd("proses-data");

console.group("Mulai pemrosesan") indents the messages inside it until groupEnd. console.time("proses-data") and console.timeEnd("proses-data") print how many milliseconds passed between them — a quick way to detect slow functions without extra tools.

debugger and Breakpoints

The debugger Statement

console.log shows a value at a single moment, but to understand flow, you need to pause execution. The debugger statement pauses code at that point while DevTools is open:

JSThe debugger statement
function hitungTotal(item) {
  let total = 0;
  for (const harga of item) {
    debugger;
    total += harga;
  }
  return total;
}
 
const hasil = hitungTotal([10000, 20000, 30000]);
console.log(hasil);

debugger; pauses execution inside the loop, giving you a chance to inspect the harga and total values in the Sources tab. When DevTools is closed, this statement is ignored and the code runs normally. debugger isn't a replacement for manual breakpoints — it's a breakpoint that's saved along with the code.

Breakpoints in DevTools

Manual DevTools breakpoints are more flexible than the debugger statement:

  • Click a line number in the Sources tab to place a breakpoint.
  • Reload the page; execution stops at that line.
  • Inspect variables in the Scope panel, and step through execution with the step buttons.

Breakpoints let you inspect the state — variables, scope, and stack — at the exact moment before a line runs. This changes debugging from guessing into observing.

Reading Errors and Stack Traces

The Anatomy of a Stack Trace

When an error occurs, the console shows a stack trace — the list of calls leading to the error point. Reading it from bottom to top reveals the path in:

JSAn error with a stack trace
function lapisKetiga() {
  throw new Error("Gagal di lapisan terdalam");
}
 
function lapisKedua() {
  lapisKetiga();
}
 
function lapisPertama() {
  lapisKedua();
}
 
lapisPertama();

throw new Error("Gagal di lapisan terdalam") produces a stack trace naming the line in lapisKetiga, then lapisKedua, then lapisPertama. The top line is the error location; the rest is the path in. Training yourself to read stack traces is the most valuable skill in debugging.

Isolating the Problem

A systematic approach you can always apply:

  • Reproduce: make sure you can trigger the error consistently.
  • Isolate: narrow the location — check one part, not everything.
  • Observe: use console.table or breakpoints to see the data.
  • Verify: after the fix, confirm the error doesn't reappear.

Most long debugging sessions happen precisely because code is changed without observing data first. A console.log at a function's entry and exit points is often already enough to find the problem location.

DevTools Tools for Real Problems

Inspecting Network Requests

The Network tab shows every request the page sends: method, status, size, and duration. This is the main tool when an API is misbehaving:

Inspecting an API request
curl -i https://jsonplaceholder.typicode.com/posts/1

curl -i in the terminal shows the status, headers, and response body — a quick way to confirm an endpoint works before blaming the JavaScript code. If curl succeeds but the app fails, the problem is in the client code; if curl fails, the problem is in the server or network.

Tracing Performance

The Performance tab records page activity and shows which tasks consume time. This is the gateway into the optimization we'll cover in episode 22: finding slow functions, expensive layouts, or repeated renders.

A common finding: a large loop that should be replaced with map, or repeated DOM operations that should be batched. Data from the Performance tab directs fixes with evidence, not guesses.

Tip

The most important debugging rule: make the error small. Break the problem into one variable you can inspect, one function you can call in isolation, or one request you can test with curl. Shrinking the problem is half of solving it.

Wrap-Up

Episode 19 trained you to be a debugger: using the Console API with the right levels and formats, pausing execution with debugger and breakpoints, reading errors along with stack traces, and leveraging the Network and Performance tabs in DevTools.

Key takeaways:

  • Use console.warn and console.error according to severity.
  • console.table displays arrays of objects far more readably.
  • debugger pauses execution while DevTools is open.
  • Read stack traces from top to bottom to trace the flow.
  • Test endpoints with curl before blaming the client code.
  • Narrow the problem before changing code — don't guess.

In the next episode 20 we'll cover modern JavaScript with linting, formatting, and tooling — automating code quality with ESLint and Prettier, setting up npm scripts, and enforcing consistent rules across the whole project. This is how professional team code is kept clean.

Learn JavaScript - Debugging and Console Tools | Learn JavaScript