Skip to content

JavaScript Tutorial JavaScript Practice Challenge

Practice: Debugging Challenges

Lesson 257 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

Each snippet below is broken on purpose. Find the bug, fix it, and press Run to check. Use the methods from the Debugging chapter: read the error, log values, isolate.

1. The variable that does not exist

script.js
JS
const userName = "Maya";
console.log("Hello, " + username);   // error on purpose
Show the fix

JavaScript is case sensitive. username is not the same as userName. Use the same spelling: console.log("Hello, " + userName).

2. The loop that reads one item too many

script.js
JS
const scores = [80, 90, 70];
let total = 0;

for (let i = 0; i <= scores.length; i++) {
  total += scores[i];
}

console.log("Average:", total / scores.length);
Show the fix

The loop condition should be i < scores.length. With <=, the last pass reads scores[3], which is undefined, so total becomes NaN. The array has indexes 0, 1 and 2.

3. The sum that became text

script.js
JS
const inputs = ["10", "20", "30"];     // imagine these came from form fields
const total = inputs.reduce((sum, value) => sum + value, 0);

console.log(total);     // expected 60
Show the fix

Form values are strings, so + joins them. Convert first: sum + Number(value). Better still, convert when you read the value from the field. See Parsing Numbers.

3b. The condition that is always true

script.js
JS
let password = "wrong";

if (password = "secret") {
  console.log("Access granted");
} else {
  console.log("Access denied");
}
Show the fix

= assigns, === compares. The assignment password = "secret" gives "secret", which is truthy, so access is always granted. Write password === "secret". (Never compare passwords like this in real code. This is only about the operator.)

4. The method that lost its object

script.js
JS
const timer = {
  seconds: 0,
  start() {
    setTimeout(function () {
      this.seconds++;            // error on purpose in strict mode, or a silent bug otherwise
      console.log("seconds:", this.seconds);
    }, 50);
  }
};

timer.start();
Show the fix

A normal function used as a callback has its own this, which is not timer. Use an arrow function, which keeps the this of the surrounding method: setTimeout(() => { this.seconds++; ... }, 50). See this in JavaScript.

5. The data that was not there yet

script.js
JS
const wait = ms => new Promise(resolve => setTimeout(() => resolve({ name: "Maya" }), ms));

async function showUser() {
  const user = wait(100);
  console.log(user.name);        // expected Maya
}
showUser();
Show the fix

wait(100) returns a promise, not the data. Without await, user.name is undefined. Write const user = await wait(100);. See async and await.

6. The list that did not update

index.html
HTML
<ul id="list"></ul>
<button id="add">Add</button>
<script>
  const items = [];
  document.querySelector("#add").addEventListener("click", () => {
    items.push("Item " + (items.length + 1));
    console.log(items.length, "items in the array");
  });
</script>
Show the fix

The array grows, but nothing draws it on the page. State changes need a render() step that updates the DOM: after items.push(...), create an <li> with textContent and append it to #list, or rebuild the list from the array.

A habit to take away

For every bug, ask three questions: What did I expect? What happened instead? What is the first place where those two differ? That is where the bug lives.