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.

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 provides different levels for different messages, and DevTools colors them so they're easy to scan:
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.
For lists of objects, console.table displays a table that's far easier to read than raw 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.
console.group groups messages, and console.time measures execution duration:
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.
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:
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.
Manual DevTools breakpoints are more flexible than the debugger statement:
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.
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:
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.
A systematic approach you can always apply:
console.table or breakpoints to see the data.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.
The Network tab shows every request the page sends: method, status, size, and duration. This is the main tool when an API is misbehaving:
curl -i https://jsonplaceholder.typicode.com/posts/1curl -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.
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.
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:
console.warn and console.error according to severity.console.table displays arrays of objects far more readably.debugger pauses execution while DevTools is open.curl before blaming the client code.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.