How to Debug JavaScript

What you’ll build or solve

You’ll identify why your code behaves incorrectly and confirm the fix works.

When this approach works best

Use this approach when you:

  • See unexpected output like undefined, NaN, or wrong results.
  • Get runtime errors in the browser console or Node terminal.
  • Need to understand how values change across multiple functions.

Start by reproducing the bug consistently. Debugging random behavior wastes time.

Skip this approach when:

  • Your editor already highlights a simple syntax error.
  • The issue comes from an external API or server outside your JavaScript.

Prerequisites

  • A JavaScript file or an HTML page with a <script> tag
  • A browser with DevTools, or Node.js installed
  • Basic knowledge of variables and functions

Step-by-step instructions

1) Log values to narrow down the issue

Use console methods to inspect what your code receives and returns. This is the fastest way to isolate simple bugs.

functionadd(a,b) {
console.log("a:",a);
console.log("b:",b);
returna+b;
}

console.log(add(2));

If b is undefined, you immediately see the issue.

You can also use:

JavaScript

console.error("Something failed");
console.warn("Unexpected value");
console.table([{ id:1 }, { id:2 }]);

Use logging for:

  • Checking function inputs
  • Verifying conditional branches
  • Inspecting API responses

If the problem becomes hard to follow, move to breakpoints.

What to look for

  • Values that are undefined or different than expected
  • Code paths that do not execute
  • Errors printed in red in DevTools

2) Set breakpoints to pause execution

Breakpoints let you stop the code exactly where you suspect a problem.

Open DevTools:

  • Chrome or Edge: Ctrl+Shift+I or Cmd+Option+I

Then:

  1. Go to the Sources tab.
  2. Click a line number to set a breakpoint.

Example:

functioncalculateTotal(price,taxRate) {
consttotal=price*taxRate;
returntotal;
}

console.log(calculateTotal(100,0.2));

Set a breakpoint on the const total line, then reload the page.

Execution pauses there. Now you can:

  • Inspect local variables in the Scope panel.
  • Hover over variables to see current values.
  • Step over the next line.
  • Step into a function call.

Check the Call Stack panel while paused. It shows which functions led to the current line, which helps when multiple functions interact.

Use breakpoints for:

  • Complex logic across multiple functions
  • Timing issues in asynchronous code
  • Bugs that logging alone cannot clarify

What to look for

  • Incorrect values in the Scope panel
  • Unexpected function order in the Call Stack
  • Code that never executes because a condition fails earlier

Examples you can copy

Example 1: Debug a loop condition

constnumbers= [1,2,3];

for (leti=0;i<=numbers.length;i++) {
console.log(numbers[i]);
}

Set a breakpoint inside the loop and watch i as it increases. You’ll notice the final iteration uses an invalid index.

Fix the condition:

for (leti=0;i<numbers.length;i++) {
console.log(numbers[i]);
}

Example 2: Debug undefined property access

constuser= { name:"Alex" };

console.log(user.age.toString());

Set a breakpoint before the property access and inspect user. You’ll see that age does not exist.

Fix with a guard:

JavaScript

if (user.age!==undefined) {
console.log(user.age.toString());
}

Or use optional chaining:

console.log(user.age?.toString());

Example 3: Debug asynchronous behavior

functionfetchData() {
setTimeout(() => {
console.log("Data loaded");
  },1000);
}

console.log("Start");
fetchData();
console.log("End");

Set a breakpoint inside the setTimeout callback. You’ll observe that execution continues before the callback runs, which explains why output order may differ from expectation.


Common mistakes and how to fix them

Mistake 1: Changing too many things at once

What you might do: edit multiple parts of the code while debugging.

Why it breaks: you lose track of which change fixed or caused the issue.

Fix: change one thing at a time and test after each change.


Mistake 2: Ignoring error messages

What you might do: overlook a red error message in DevTools.

Why it breaks: error messages often include the exact line number and cause.

Fix: click the linked line in the Console to jump directly to the issue.


Mistake 3: Logging after the error occurs

What you might do: add console.log() below a line that throws an error.

Why it breaks: the script stops before reaching the log.

Fix: move logs above the suspected problem line or use a breakpoint.


Troubleshooting

If breakpoints do not pause execution, confirm the correct file is loaded in DevTools.

If DevTools shows a different file version, refresh the page.

If Node exits immediately, add a log at the top of the file to confirm execution.

If you see “undefined is not a function,” check that the variable actually holds a function.

If the bug appears only sometimes, confirm you can reproduce it consistently before debugging.


Quick recap

  • Reproduce the bug before debugging.
  • Use console logs to inspect values quickly.
  • Set breakpoints for complex or multi-step logic.
  • Inspect variables in the Scope panel.
  • Use the Call Stack to understand function order.
  • Fix one issue at a time and retest.