cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Debugging in the browser

Pause JavaScript with browser breakpoints, step through function calls, and inspect values with Scope and Watch panels.

By the end you can
  • 01
    Pause code on purposeUse line breakpoints, conditional breakpoints, and debugger statements.
  • 02
    Move through a paused programChoose Step over, Step into, Step out, or Resume for the question you are asking.
  • 03
    Inspect values while pausedRead Local, Closure, and Global scope sections, and pin Watch expressions.

Debugging means pausing the movie

A bug is a moment when the program and your expectation split apart. The browser debugger helps you find that moment by pausing JavaScript while it is running. Once paused, you can read the current line, move one step at a time, and inspect the values the program is actually using.

Earlier lessons used the DevTools console and console.log to print clues. That is still useful. But printing is like asking an actor to shout notes while the play continues. A breakpoint is different: it freezes the scene so you can look around.

Important honesty note

The step-by-step player in this course is a guided replay of code we recorded. It is not a debugger. This lesson uses that replay to explain the ideas, then asks you to try the real debugger in your own browser DevTools.

Real-life analogyA breakpoint is the pause button on a movie

Imagine a mystery movie. If you let it play at full speed, you might miss the clue on the desk. Pause at the right frame and the clue is obvious. Browser debugging is the same habit for code: stop at one statement, look carefully, then continue.

In real life: Pause at the exact scene
In JavaScript: Set a line breakpoint on the exact statement
In real life: Look at props and actors
In JavaScript: Inspect variables in Scope
In real life: Advance one frame
In JavaScript: Step over or step into the next operation

Where the analogy stops: A movie frame is passive. A paused program is live: changing values in DevTools can change what happens next, so beginners should inspect first and edit only when they mean to.

Open Chrome or Edge DevTools and choose Sources. In Firefox, the panel is called Debugger. In Safari, use Sources after enabling developer features. The names vary, but the ideas in this lesson are the same.

Breakpoints: tell the browser where to pause

BREAKPOINTS

A breakpoint is a marker you place on code. When JavaScript reaches that spot, DevTools pauses before moving on. In most browsers you set a line breakpoint by opening a file in the debugging panel and clicking the line number.

Useful breakpoint types include:

  • Line breakpoint: pause every time a line runs.
  • Conditional breakpoint: pause only when an expression is true, such as i === 50 in a loop.
  • Logpoint: print a message from that line without pausing and without editing the file.
  • Pause on exceptions: stop where an error is thrown. Many browsers can also pause on caught exceptions.
  • DOM and event listener breakpoints: pause when a page node changes or an event such as a click fires. These are browser features around JavaScript, not new JavaScript syntax.
Breakpoint ideas you will see in DevToolsJavaScript
// Line breakpoint: pause whenever this line runs.total = total + price; // Conditional breakpoint: pause only when this is true.i === 50 // Logpoint: print a message without pausing."total is", total // Pause on exceptions: stop where an error is thrown.throw new TypeError("price must be a number");
Breakpoint tools at a glance
ToolWhen it helpsWhat happens
Line breakpointYou know the suspicious lineExecution pauses every time that line is reached
Conditional breakpointA loop or repeated function only fails for one caseExecution pauses only when the condition is true
LogpointYou need a quick printed clue without editing sourceDevTools logs and keeps running
Pause on exceptionsAn error happens before you know whereExecution pauses where the error is thrown

Conditional breakpoints are especially beginner-friendly in loops. If a list has 100 items and only item 50 is wrong, pausing 50 times is exhausting. A condition such as i === 50 lets the browser skip straight to the interesting case.

The debugger statement

REAL DEVTOOLS

JavaScript has a built-in statement named debugger. When DevTools is open, the browser pauses on that line as if you had placed a breakpoint there. When DevTools is closed, browsers normally ignore it and keep running.

This is useful when a file is hard to find in bundled source, or when you want a temporary pause in a small local experiment. It is also easy to forget. Remove debugger; before committing or sharing code.

Real debugger statement demo
Source inside the demo pagePop out in the code editor (opens in a new tab)JavaScript
function handleDebugClick() {  const label = "Debug button";  debugger;  console.log(label + " finished");} document.querySelector("button").addEventListener("click", handleDebugClick);
Real iframe demoOpen DevTools first
Try it yourself

Open DevTools first, then click the button inside the framed demo. The code is predefined and harmless; the important line is debugger;.

This is a real browser feature, not the lesson replay player. Remove debugger; before sharing code.
What just happened?

The button lives inside a sandboxed iframe with predefined code. If your DevTools were open, the browser paused on the actual debugger; line. If DevTools were closed, nothing special happened and the code continued.

Stepping over, into, and out

STEP THROUGH

Once execution is paused, the toolbar gives you movement buttons. In Chrome and Edge DevTools, Resume is F8, Step over is F10, Step into is F11, and Step out is Shift + F11. Other browsers show similar buttons, but shortcuts can differ.

The three stepping choicesJavaScript
totalCart(items);          // Step into opens totalCartapplyDiscount(total);    // Step over runs it and stays herereturn roundPrice(value); // Step out finishes this function
Real-life analogyStepping is how closely you read a book

If a chapter looks trustworthy, you might read its title and keep moving. If it may contain the clue, you open it. If you are already inside and realize it is not the problem, you finish it and return to the caller.

In real life: Read the chapter title and continue
In JavaScript: Step over: run the function call without opening it
In real life: Open the chapter and read each paragraph
In JavaScript: Step into: enter the called function
In real life: Finish this chapter and return to the main story
In JavaScript: Step out: finish the current function and pause at its caller

Where the analogy stops: A book waits forever while you choose. Real pages may have timers, events, or network work happening elsewhere, so pause only as long as you need.

The next replay uses one real buggy program at two granularities. The cart should total 30 and apply a 10 percent discount once, so the right answer is 27. The bug applies the discount twice. Switch between Step into and Step over and notice that the final result is the same real value: 24.3.

Same buggy cart, two debugger moves
Step 0 of 24Ready
Your turn: follow the blue line

Step into opens each helper call. Watch the second applyDiscount call reveal the double-discount bug.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
 function roundPrice(amount) {  return Math.round(amount * 100) / 100;} function applyDiscount(amount) {  const discounted = amount * 0.9;  return roundPrice(discounted);} function totalCart(prices) {  let total = 0;  for (const price of prices) {    total = total + price;  }  const firstPass = applyDiscount(total);  const finalTotal = applyDiscount(firstPass);  return finalTotal;} console.log(totalCart(items));
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Choose how the debugger treats function calls

Both recordings come from the same real run. Only the granularity changes.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The bug is line 18: applyDiscount(firstPass). Step into makes that obvious because you see amount become 27 inside the second helper call. Step over still runs the helper, but it hides the helper’s internal lines and shows only the returned value. Step out would matter if you were already inside roundPrice and wanted to finish that helper and return to applyDiscount.

Watch expressions and the Scope panel

SIMULATOR

Pausing is useful because the debugger shows what names mean at that exact moment. The Scope panel usually groups values into sections. Local means variables in the current function. Closure means variables remembered from an outer function; the Closures lesson goes deeper later. Global or Script means top-level values.

A Watch expression is an expression you pin to the debugger, like a gauge on a dashboard. Every time execution pauses, the browser tries to evaluate it using the current values. Good watches are small: subtotal * discountRate, items.length, or total === 27.

Real-life analogyScope is a set of drawers

When the program pauses, the current function can reach some drawers easily and others only through outer links. The Scope panel is DevTools showing those reachable drawers.

In real life: Top drawer right in front of you
In JavaScript: Local: names in the current function
In real life: A drawer the function brought from home
In JavaScript: Closure: remembered outer names
In real life: The big shared filing cabinet
In JavaScript: Global/Script: top-level names

Where the analogy stops: Real scope rules are precise and lexical. The drawer picture helps you look in the right place, but later lessons explain exactly how JavaScript decides which drawer a name comes from.

Debugger panel simulator: Scope and Watch
Program being inspectedPop out in the code editor (opens in a new tab)JavaScript
const subtotal = 30;const discountRate = 0.1; function applyDiscount(amount) {  const discounted = amount - amount * discountRate;  return Math.round(discounted * 100) / 100;} const total = applyDiscount(subtotal);
Paused on line 6Paused before the helper returns

Scope · Local

amount30
discounted27

Scope · Global/Script

subtotal30
discountRate0.1

Watch

amount * discountRate3
Math.round(discounted * 100) / 10027
Step 1 of 2Paused before the helper returns

Local values belong to applyDiscount. Global values were created outside the function. The Watch panel recomputes expressions from the paused values.

A clearly labeled simulation of a paused debugger panel. The source and watch values are computed from real lesson functions; this widget itself is not DevTools.
Use watches gently

Watch expressions should be safe to run repeatedly. Avoid expressions that change the page or update data while you are learning. A watch such as cart.add() would change the cart every time the debugger evaluates it.

Which tool fits?

INTERACTIVE

Debugging is faster when you pick the smallest tool that answers your question. Sort each scenario by the kind of debugger tool you would reach for first.

Which debugging tool fits?
  • Stop every time a suspicious assignment runs
  • A loop fails only when i === 50
  • Print total from production-like code without editing the file
  • Leave a quick note while writing a tiny local experiment
  • Keep checking subtotal * discountRate on every pause
  • See the current function's price, total, and nearby variables
  • The code throws before you know which line caused it
  • A library catches the error before the console shows the real source
Try it yourself
0 of 8 correct

Drop each scenario into the best family of tools. The explanation names the specific tool, such as line breakpoint, conditional breakpoint, logpoint, Watch, console.log, or pause on exceptions.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Where you will use this

Browser debugging is most useful when the code is correct-looking but the values are not. A shopping cart, form validator, quiz score, or button state can all fail because one value changed earlier than you expected.

Buggy cart codePop out in the code editor (opens in a new tab)JavaScript
const items = [20, 10]; function roundPrice(amount) {  return Math.round(amount * 100) / 100;} function applyDiscount(amount) {  const discounted = amount * 0.9;  return roundPrice(discounted);} function totalCart(prices) {  let total = 0;  for (const price of prices) {    total = total + price;  }  const firstPass = applyDiscount(total);  const finalTotal = applyDiscount(firstPass);  return finalTotal;} console.log(totalCart(items));

A practical debugging routine looks like this:

  1. Describe the wrong behavior in one sentence.
  2. Set a breakpoint before the value first looks suspicious.
  3. Step over trusted helpers; step into helpers that may hide the bug.
  4. Read Scope before guessing. Add Watch expressions for values you keep recomputing.
  5. Fix the smallest line, then rerun from the start.

Common misconceptions

“Step over means skip this function.”

Step over still runs the function. It only skips opening that function’s body in the debugger view.

“The Scope panel shows what variables will be later.”

Scope is a snapshot of now: the paused line and the values reachable at that moment.

“A watch expression is just text.”

DevTools evaluates it. Keep watches side-effect free so inspecting does not change the program.

“The course replay is DevTools.”

The replay is recorded from real functions to teach the path. The real browser debugger is in DevTools.

“debugger; is harmless to leave in code.”

It is temporary. It can interrupt developers who open DevTools and makes shared code look unfinished.

Similar tools, different jobs
PairUse this whenNot this
Breakpoint vs console.logYou need to pause and inspect several valuesYou only need a quick printed clue
Step over vs Step intoYou trust the helper and want its resultYou need to inspect the helper line by line
Scope vs WatchYou want all nearby variablesYou want one pinned expression every pause

Practice: pause, inspect, decide

5 EXERCISES
Exercise 1 · Warm-upPredict a paused value

Imagine a breakpoint on return result;. What value would result have in the Scope panel?

Starter codePop out in the code editor (opens in a new tab)JavaScript
function double(number) {
  const result = number * 2;
  return result;
}
console.log(double(6));

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeSet a conditional breakpoint

    A loop fails only on item 50. What condition would you type so the browser pauses only when i is 50?

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeUse debugger, then remove it

      Add a temporary pause with debugger;, test it with DevTools open, and then remove it. Which statement must not be left behind?

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeWatch an expression

        If execution pauses after line 3, what would a Watch expression for subtotal * discountRate show?

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const subtotal = 30;
        const discountRate = 0.1;
        const total = subtotal - subtotal * discountRate;
        console.log(total);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeFind the double-discount bug

          In the cart replay, which line applies the discount for the second time?

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            7 QUESTIONS

            Pick an answer, read the explanation, and connect it back to the debugging move you would make in DevTools.

            Lesson quiz · 7 questionsScore: first tries count
            1. Question 1 of 7What is a breakpoint?

              Choose an answer to see the explanation.

            2. Question 2 of 7When does a debugger; statement pause?

              Choose an answer to see the explanation.

            3. Question 3 of 7A line calls applyDiscount(total). You trust the helper and want to stay in the current function. Which button fits?

              Choose an answer to see the explanation.

            4. Question 4 of 7What does the double-discount program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function discount(amount) {
                return amount * 0.9;
              }
              const first = discount(30);
              const second = discount(first);
              console.log(second);

              Choose an answer to see the explanation.

            5. Question 5 of 7Which Scope section normally shows variables created inside the currently paused function?

              Choose an answer to see the explanation.

            6. Question 6 of 7Which tool prints a message at a line without pausing or editing the source file?

              Choose an answer to see the explanation.

            7. Question 7 of 7What does the loop print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              let total = 0;
              for (let i = 1; i <= 3; i = i + 1) {
                total = total + i;
              }
              console.log(total);

              Choose an answer to see the explanation.

            Key takeaways

            • Breakpoints pause code so you can inspect the exact moment a value changes.
            • debugger; is a real temporary pause when DevTools is open; remove it afterward.
            • Step over runs a call without opening it. Step into opens it. Step out finishes the current function.
            • Scope shows reachable values now; Watch pins expressions you want to recalculate on each pause.
            • Use the course replay for learning, and your browser’s DevTools for real debugging.

            Remember the one-liner.
            Browser debugging means pausing real JavaScript, moving one step at a time, and checking values before you guess.

            Up next: Coding style & naming.

            CompleteFrontend Clear concepts. Working examples.