Debugging JavaScript with Breakpoints: Complete Guide
Stop guessing what your code does. Learn every breakpoint type in Chrome DevTools: line breakpoints, conditional breakpoints, logpoints, DOM breakpoints, and event listener breakpoints.
Breakpoints let you pause JavaScript execution at a specific line and inspect everything: variable values, the call stack, and the current scope. They are more powerful than a print statement because you do not need to know what to log in advance.
You can explore the entire program state at the moment of pause, then step forward one line at a time to watch it change.
Open Chrome DevTools (F12 or Ctrl+Shift+I), click the Sources tab, and navigate to your JavaScript file in the left file tree. You are ready to set breakpoints.
Line breakpoints
The simplest breakpoint: click a line number in the Sources panel. A blue marker appears. When that line is about to execute, the debugger pauses.
function calculateTotal(items) {
let total = 0;
for (const item of items) {
total += item.price; // Click the line number here to set a breakpoint
}
return total;
}When paused, you see:
- Scope pane (right): all local variables, closure variables, and global variables with their current values
- Call Stack pane: the chain of function calls that led to this point
- The line itself: highlighted in blue, about to execute
From here you can inspect anything. Hover over the item variable to see its value, type total in the Console to check the running sum, or open the Scope pane to browse every variable at once.
Stepping through code
Once paused, use these controls to move forward:
| Key | Action | What it does |
|---|---|---|
| F9 | Resume | Continues execution until the next breakpoint |
| F10 | Step Over | Runs the current line and moves to the next one in the same function |
| F11 | Step Into | If the current line calls a function, enters that function |
| Shift+F11 | Step Out | Runs the rest of the current function and pauses at the caller |
function outer() {
const x = computeX(); // Step Over: runs computeX, pauses on next line
const y = process(x); // Step Into: enters the process function body
return y;
}Step Over is for when you trust the function being called and just want to see the result. Step Into is for when you need to debug inside that function.
Step Out is your escape hatch when you have seen enough inside a function and want to jump back to the caller.
Conditional breakpoints
Right-click a line number and choose Add conditional breakpoint. Enter any JavaScript expression, and the debugger pauses only when that expression evaluates to true:
for (let i = 0; i < 10000; i++) {
process(items[i]);
// Conditional breakpoint on next line: i === 5000
}The loop runs 10,000 times but the debugger pauses only once, when the counter reaches 5,000. Without the condition, you would have to press Resume 5,000 times.
Common conditional breakpoint patterns:
| Condition | Use case |
|---|---|
i === 99 | Pause on the 100th loop iteration |
item.id === 42 | Pause when processing a specific data item |
value === undefined | Pause when a variable unexpectedly becomes undefined |
error.message.includes("timeout") | Pause only on timeout errors |
items.length > 100 | Pause when a list grows too large |
Logpoints
A logpoint prints a message to the console every time the line would execute, without pausing. Right-click a line number and choose Add logpoint:
function processItems(items) {
for (const item of items) {
applyDiscount(item); // Logpoint: "Processing item", item.id, item.price
updateUI(item);
}
}Each iteration prints the item ID and price. The code runs at full speed, no pausing, but you see the values flow through the console.
Use logpoints instead of adding temporary print statements to your code. They live in DevTools, not in your source files, so there is no risk of committing debug logging to production.
DOM breakpoints
DOM breakpoints pause when a specific DOM element changes. Right-click an element in the Elements panel and choose:
- Break on subtree modifications -- pauses when a child element is added, removed, or changed
- Break on attribute modifications -- pauses when an attribute like class, style, or disabled changes
- Break on node removal -- pauses when the element is removed from the DOM
These are essential for tracking down "who changed my element?" bugs. Instead of searching every line that touches the DOM, set a DOM breakpoint, trigger the bug, and the debugger pauses at the exact line that modified the element.
Event listener breakpoints
In the Sources panel, expand the Event Listener Breakpoints section in the right sidebar. You can pause on entire categories or specific events:
- Mouse > click -- pauses when any click event fires
- Keyboard > keydown -- pauses when any key is pressed
- Timer > setTimeout -- pauses inside setTimeout callbacks
This is how you find what code runs when a user clicks something, without searching for every event listener registration in the codebase. Enable the breakpoint, click the element, and the debugger pauses inside the handler.
The debugger statement
You can set a breakpoint directly in your code with the debugger keyword:
function suspiciousFunction(data) {
const result = transform(data);
debugger; // Pauses here if DevTools is open
return validate(result);
}When DevTools is open, the debugger statement acts as a hardcoded breakpoint. When DevTools is closed, it has no effect.
This is useful during development, but remember to remove these statements before committing. A linter rule can catch any that slip through.
Watch expressions
In the Sources panel, the Watch section lets you monitor any JavaScript expression that updates with each step:
// Add these watch expressions:
// items.length
// total + tax
// user.name !== ""Watch expressions re-evaluate every time the debugger pauses or steps. They are good for tracking derived values that are not simple variables, such as a filtered array's length or the number of keys on an object.
Practical debugging workflow
When you encounter a bug, follow this sequence:
- Reproduce the bug. Know the exact steps that trigger it.
- Set a breakpoint at the earliest point where you suspect things go wrong.
- Trigger the bug so the debugger pauses.
- Inspect the Scope pane. Are variables what you expect?
- Step through line by line with F10. Watch values change.
- Identify the exact line where a value diverges from what you expect.
- Fix the code, remove breakpoints, and verify.
Most bugs are found on the first or second breakpoint. If the first breakpoint shows correct values, step forward. If the values are wrong at the first breakpoint, the bug is earlier in the call stack. Use the Call Stack pane to click up to the caller and inspect where the bad value originated.
For performance-focused debugging, see the Chrome DevTools performance tuning guide. For programmatic error handling, see the try...catch guide.
Rune AI
Key Insights
- Click a line number in Sources to set a regular line breakpoint.
- Right-click and choose Conditional Breakpoint to pause only when an expression is true.
- Use logpoints to print values in hot code without stopping execution.
- DOM breakpoints pause on subtree modifications, attribute changes, or node removal.
- Event listener breakpoints pause when specific events fire, like click or keydown.
- Use Step Over (F10), Step Into (F11), and Step Out (Shift+F11) to navigate paused code.
Frequently Asked Questions
What is the difference between Step Over and Step Into?
Can I set breakpoints that only pause on the 100th iteration of a loop?
What is a logpoint and when should I use it?
Conclusion
Breakpoints turn debugging from guesswork into certainty. Line breakpoints let you pause anywhere. Conditional breakpoints let you pause only when it matters. Logpoints let you observe without stopping. DOM and event listener breakpoints catch problems that line breakpoints miss. The debugger is the most powerful tool in your DevTools. Use it before console.log.
More in this topic
Using Decorators for Logging in JS Architecture
Learn how JavaScript decorators wrap class methods to add logging without touching the original code, including setup with Babel and how execution order works.
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.