Why console.log Is the Wrong First Tool

Console.log gives you one snapshot of one value at one point in time. To learn anything more, you add another log, refresh, scroll output, repeat. Five iterations in, you've spent 10 minutes that a 2-second breakpoint would have answered. Console.log has a place — for fast checks where you already know what you're looking for. For everything else, the debugger is the right tool.

Setting Breakpoints

Open DevTools (F12), go to Sources, find your file (Cmd/Ctrl+P searches by name), click any line number to set a breakpoint. When that line runs, execution pauses. The Scope panel on the right shows every variable in scope. You can hover any variable in source to see its current value.

The four buttons at the top of the right pane: Resume (F8), Step Over (F10), Step Into (F11), Step Out (Shift+F11). Memorize these — they're your entire navigation vocabulary.

Conditional Breakpoints

The killer feature most devs never use. Right-click a line number → "Add conditional breakpoint" → enter an expression. Execution only pauses when the expression is true. Perfect for "this loop runs 1000 times but I only care about the iteration where user.id === 'abc'":

// Conditional breakpoint expression:
user.id === "abc"

Same menu has "Add logpoint" — type any expression and its value gets logged when the line runs, without pausing. Logpoints replace 90% of console.log usage and don't ship to production.

Async Stack Traces

Modern DevTools follows promise chains across async boundaries. When you pause inside a then() callback, the stack shows where the promise was created — not just the microtask runtime. This makes debugging async code roughly 10x easier than it was in 2018. Combined with "pause on exception" (the octagon icon in Sources), you catch async errors at the throw site instead of in some distant catch.

The Network Tab

For anything API-related, the Network tab beats every alternative. Filter by Fetch/XHR. Each row shows method, status, time, and size. Click for headers, payload, response, and a waterfall view of timing. Three tricks worth knowing:

  • Right-click → Copy as cURL. Reproduce any request in terminal in one click.
  • Throttling. Top of Network tab — simulate slow 3G to find loading-state bugs.
  • Block request URL. Right-click any request → Block. Verify your error handling actually works.

Watch Expressions and Live Edits

The Watch panel (top right) lets you pin expressions that update at every pause. Type user.permissions.length once and see it update as you step through. The Console at any pause point lets you evaluate any expression in the current scope — modify variables, call functions, test fixes without reloading.

Performance Profiling

For "the page feels slow" complaints, the Performance tab is the only honest answer. Click record, do the slow action, click stop. The flame chart shows exactly where time went — JavaScript execution, layout, paint, network. Look for tall narrow blocks (slow function) and wide sections of yellow (scripting). The Bottom-Up tab aggregates by function so you see total time spent across calls.

Memory Leaks

For SPAs that get slower over time, take a heap snapshot, do the suspicious action 5 times, take another snapshot, then compare. Detached DOM nodes that survive a snapshot are usually the culprit — a closure or event listener is keeping them alive. The Allocations tab shows what's being created on each interaction.

A Practical Debugging Workflow

  1. Reproduce the bug. If you can't reproduce it, you can't fix it. Step one is always nailing down the steps.
  2. Form a hypothesis about which function is wrong. Set a breakpoint there.
  3. Run the reproduction. When the breakpoint hits, inspect — is your hypothesis right?
  4. If yes, step through and find the exact bad line. If no, move the breakpoint earlier and repeat.
  5. Test the fix in the Console at the pause point before changing source.

For pasting suspect code into an isolated environment to test in seconds, the online JavaScript editor runs without setup. For deep code review patterns, see the code review best practices guide.

Bottom Line

DevTools has been mature for a decade and most developers still use 5% of it. Spending one afternoon learning conditional breakpoints, logpoints, async stack traces, and the Performance tab pays back every week for the rest of your career. Console.log isn't wrong — it's just the slowest possible debugger.