Using the JavaScript Debugger & Breakpoints
Instead of printing values to the console using console.log(), you can use breakpoints and the debugger; statement to pause code execution, inspect memory state, and step through code line-by-line.
This guide covers code-based breakpoints, DevTools breakpoints, and conditional debugging.
1. The debugger; Statement (Code-Based Breakpoint)
JavaScript has a built-in statement designed specifically for triggering debugging sessions: the debugger; keyword.
When the browser or Node.js encounters this statement while Developer Tools are open, it automatically pauses execution at that line, acting exactly like a breakpoint.
Code Example
function calculateInvoice(price, taxRate) {
const tax = price * taxRate;
// The browser will pause here if DevTools is open
debugger;
const total = price + tax;
return total;
}
calculateInvoice(100, 0.08);Important: Always remove debugger; statements before deploying code to production. If left in production, it will pause the app for any user who happens to have their DevTools panel open.
2. Browser DevTools Breakpoints (UI-Based Breakpoints)
If you cannot or do not want to modify your source code to debug, you can set breakpoints directly in the browser's DevTools user interface.
Step-by-Step Guide
- Open your page in the browser and open DevTools (
F12orCmd + Option + I). - Go to the Sources tab (called Debugger in Firefox).
- Find your JavaScript file in the left panel and click to open it.
- Locate the line you want to pause on.
- Click directly on the line number. A blue marker will appear, showing that a breakpoint is now active.
- Trigger the action in your app (e.g., click a button). The browser will freeze execution at that line.
3. Conditional Breakpoints (Selective Pausing)
A conditional breakpoint will only pause code execution if a specific condition evaluates to true. This is incredibly useful for loops, animations, or event handlers that trigger frequently.
Step-by-Step Guide
- Open your code in the DevTools Sources / Debugger panel.
- Right-click on the line number.
- Select Add conditional breakpoint....
- Type your condition (which can be any valid JavaScript expression), for example:
or:
item.quantity === 0index === 49 - Press Enter. An orange or yellow marker will appear on the line number.
- The app will run smoothly and only pause when your condition is met.
4. Inspecting Scopes (Local, Closure, and Global)
When your code is paused, the right-hand panel of your browser's DevTools contains a Scope section. This is your command center for understanding where variables are defined and what values they hold.
Instead of scrolling through your code to find where a variable is declared, the Scope pane organizes all active variables into their specific scopes:
A. Local Scope
Contains variables declared within the currently active function.
- What you'll see: Function parameters, variables declared using
let,const, orvarinside that function, and the specialthisreference. - Example: If you pause inside
function greet(name) { let message = "Hi"; },nameandmessagewill be under Local.
B. Closure Scope
If a function is defined inside another function, it remembers variables from the outer function even after the outer function finishes executing.
- What you'll see: Variables from the parent/outer scopes that the inner function accesses.
- Example: If you have an inner function inside a
createCounterfunction, you will see a Closure (createCounter) item containing the counter's state variables.
C. Script and Global Scopes
- Script Scope: Contains variables declared at the top-level of a script file using
letorconst. - Global Scope: Contains variables that are accessible from absolutely anywhere in your environment (like the
windowobject in browsers orglobalin Node.js), plus variables declared globally usingvar.
5. Watch Expressions: Filtering Through Many Variables
If your application has hundreds of variables and the Scope list is too cluttered, you can use the Watch section in the right panel:
- Expand the Watch pane in DevTools (usually located above the Scope pane).
- Click the
+(Add expression) button. - Type the exact variable or property name you want to track (e.g.,
user.profile.idorcount). - Press Enter.
- As you step through your code line-by-line, the Watch section will show you the real-time value of only that variable, ignoring all the rest.
6. How to Navigate Code While Paused (Debugger Controls)
Once your debugger pauses execution (either from a breakpoint or a debugger; statement), you will see control buttons in the top-right corner of the DevTools panel (or at the top of the screen).
Here is what each control button does:
| Button | Name | Shortcut | Description |
|---|---|---|---|
â–¶ | Resume execution | F8 or Cmd + \ | Runs code normally until it encounters the next breakpoint. |
↷ | Step over | F10 or Cmd + ' | Executes the next line of code. If the line contains a function call, it runs the function in the background without jumping inside it. |
↓ | Step into | F11 or Cmd + ; | Steps inside the function call on the current line so you can debug the function's internal lines. |
↑ | Step out | Shift + F11 | Finishes running the current function and pauses at the line right after this function returned. |
ďą„ | Step | F9 | Executes the next expression/line of code, stepping inside if possible. |
đźš« | Deactivate breakpoints | Cmd + F8 | Temporarily disables all breakpoints without deleting them. |