All topics
Testingbeginner

Debugging with the Browser DevTools Debugger

Using breakpoints, the call stack panel, and watch expressions in browser DevTools to pause execution and inspect program state at a specific point.

The browser DevTools debugger is a genuinely essential everyday tool for diagnosing bugs, and while console.log is a perfectly valid quick-and-dirty debugging technique, understanding how to use actual breakpoints and the debugger's inspection tools is expected baseline knowledge for any JavaScript developer, and interviewers occasionally probe it directly to check for real hands-on debugging experience beyond just reading error messages.

Using the debugger is like pausing a live orchestra performance mid-piece to walk up and inspect exactly which notes each individual musician is currently holding and where they are in their own sheet music (the call stack), rather than only being able to listen to a recording afterward and guess, from the overall sound (console.log output), what any specific musician must have been doing at any given moment.

Key Concepts

1
A breakpoint pauses code execution at a specific line, right before it runs, letting you inspect the exact state of all variables in scope at that precise moment — set by clicking a line number in the DevTools 'Sources' panel, or by adding a literal debugger; statement directly in your source code, which has the exact same pausing effect whenever DevTools is open and code execution reaches that line (with zero effect at all if DevTools isn't open, making it safe, if a bit sloppy, to accidentally leave in). Conditional breakpoints let you pause only when a specific expression evaluates to true, invaluable for a bug that only manifests on, say, the 500th iteration of a loop, where a plain breakpoint would force you to manually resume hundreds of times first.
debugger;
2
Once paused, the debugger exposes the full call stack — showing every function currently in progress, from the one you're paused in all the way back to wherever execution originally started — letting you click through each frame to inspect that specific function's local variables and its own this binding at that point in the call chain. 'Step over' executes the current line and pauses again on the next one without diving into any function it calls; 'step into' does dive into the next function call's own execution instead, letting you follow exactly what an unfamiliar function actually does line by line; 'step out' finishes executing the entire current function and pauses again immediately after it returns to its caller.
this
3
Watch expressions let you register a specific expression (like user.address.city or items.length) that DevTools continuously re-evaluates and displays every time execution pauses, without you needing to manually navigate the scope panel to check it repeatedly — genuinely useful for tracking one specific value's evolution across many step-throughs of a loop, rather than re-inspecting the same nested object path by hand every single pause.
user.address.cityitems.length