JavaScript Tutorial

JavaScript Project: Quiz

A scored multiple-choice quiz stored as an array of questions. Show the score at the end.

What you will build

A four-question quiz. Each item is a prompt, three choices, and the index of the right answer. The page shows one question at a time. A click on a choice records the score and advances. After the last item, the page shows how many were correct.

The questions live in an array, not in duplicated HTML blocks. Adding a fifth question is another object in the list. The render function already knows how to draw it.

Open an example with Try it in JavaScript. That loads /javascript/try — a live page and a console.

Methods you will use

MethodJob on this page
array of questionsStores prompt, choices, and the correct index
clickSelects an answer and moves to the next item
scoreCounts how many choices matched answer
forEachBuilds one button per choice
textContentWrites the prompt, the progress, and the final score

Store the correct answer as an index, not as a string. Then a later wording change does not break the check. Compare choiceIndex === question.answer.

Build in slices

Shell markup: a progress line, a prompt, a box for choice buttons, and a result line that stays empty until the end.

Example

<p id="progress">Question 1 of 4</p>
<h2 id="prompt"></h2>
<div id="choices"></div>
<p id="result"></p>

The data is an array of objects. Keep the copy short. Three choices each. answer is 0, 1, or 2.

Example

const questions = [
  {
    prompt: "Which method writes text into an element?",
    choices: ["textContent", "prompt()", "location.reload()"],
    answer: 0
  },
  {
    prompt: "What does addEventListener(\"click\") wait for?",
    choices: ["A timer", "A mouse click", "A network response"],
    answer: 1
  },
  {
    prompt: "Which value is an array?",
    choices: ["{ a: 1 }", "[1, 2, 3]", "\"1, 2, 3\""],
    answer: 1
  },
  {
    prompt: "What does array.length report?",
    choices: ["The last index", "The number of items", "The first item"],
    answer: 1
  }
];

Render the current index. Each button remembers its index in a closure. After a click, either score and advance, or show the final line and hide the buttons.

Example

<p id="progress"></p>
<h2 id="prompt"></h2>
<div id="choices"></div>
<p id="result"></p>
<script>
  const questions = [
    { prompt: "Which method writes text into an element?", choices: ["textContent", "prompt()", "alert()"], answer: 0 },
    { prompt: "What does array.length report?", choices: ["The last index", "The number of items", "The first item"], answer: 1 }
  ];
  let index = 0;
  let score = 0;
  const promptEl = document.getElementById("prompt");
  const choicesEl = document.getElementById("choices");
  const progressEl = document.getElementById("progress");
  const resultEl = document.getElementById("result");

  function showQuestion() {
    const item = questions[index];
    progressEl.textContent = "Question " + (index + 1) + " of " + questions.length;
    promptEl.textContent = item.prompt;
    resultEl.textContent = "";
    choicesEl.replaceChildren();
    item.choices.forEach(function (label, choiceIndex) {
      const button = document.createElement("button");
      button.type = "button";
      button.textContent = label;
      button.addEventListener("click", function () {
        if (choiceIndex === item.answer) score += 1;
        index += 1;
        if (index < questions.length) showQuestion();
        else showScore();
      });
      choicesEl.appendChild(button);
    });
  }

  function showScore() {
    progressEl.textContent = "Done";
    promptEl.textContent = "Quiz complete";
    choicesEl.replaceChildren();
    resultEl.textContent = "You scored " + score + " out of " + questions.length + ".";
  }

  showQuestion();
</script>

Run this at /javascript/try with Try it in JavaScript. Click every first choice once to confirm the score is not always four.

Complete document

This file is the quiz you would keep. Choice buttons stack as a column. A Restart button returns index and score to zero without reloading. The questions stay in one array at the top of the script.

Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Quiz</title>
  <style>
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      background: #fefce8;
      font-family: "Segoe UI", system-ui, sans-serif;
      color: #1c1917;
    }
    .card {
      width: min(26rem, 92vw);
      background: #fffbeb;
      border: 1px solid #fde68a;
      padding: 1.4rem 1.5rem 1.5rem;
    }
    h1 { margin: 0 0 0.35rem; font-size: 1.4rem; }
    #progress { margin: 0 0 0.85rem; color: #78716c; }
    #prompt { margin: 0 0 0.9rem; font-size: 1.15rem; }
    #choices { display: grid; gap: 0.45rem; }
    button {
      text-align: left;
      padding: 0.55rem 0.7rem;
      border: 1px solid #fde68a;
      background: #fff;
      font: inherit;
      cursor: pointer;
    }
    button:hover { background: #fef9c3; }
    #restart {
      margin-top: 0.9rem;
      background: #854d0e;
      color: #fffbeb;
      border: 0;
      font-weight: 700;
      display: none;
    }
    #result { margin: 0.85rem 0 0; font-weight: 700; }
  </style>
</head>
<body>
  <article class="card">
    <h1>JavaScript Quiz</h1>
    <p id="progress"></p>
    <h2 id="prompt"></h2>
    <div id="choices"></div>
    <p id="result"></p>
    <button id="restart" type="button">Restart</button>
  </article>
  <script>
    const questions = [
      {
        prompt: "Which method writes text into an element?",
        choices: ["textContent", "prompt()", "location.reload()"],
        answer: 0
      },
      {
        prompt: "What does addEventListener(\"click\") wait for?",
        choices: ["A timer", "A mouse click", "A network response"],
        answer: 1
      },
      {
        prompt: "Which value is an array?",
        choices: ["{ a: 1 }", "[1, 2, 3]", "\"1, 2, 3\""],
        answer: 1
      },
      {
        prompt: "What does array.length report?",
        choices: ["The last index", "The number of items", "The first item"],
        answer: 1
      }
    ];

    let index = 0;
    let score = 0;
    const promptEl = document.getElementById("prompt");
    const choicesEl = document.getElementById("choices");
    const progressEl = document.getElementById("progress");
    const resultEl = document.getElementById("result");
    const restartBtn = document.getElementById("restart");

    function showQuestion() {
      const item = questions[index];
      progressEl.textContent = "Question " + (index + 1) + " of " + questions.length;
      promptEl.textContent = item.prompt;
      resultEl.textContent = "";
      restartBtn.style.display = "none";
      choicesEl.replaceChildren();
      item.choices.forEach(function (label, choiceIndex) {
        const button = document.createElement("button");
        button.type = "button";
        button.textContent = label;
        button.addEventListener("click", function () {
          if (choiceIndex === item.answer) score += 1;
          index += 1;
          if (index < questions.length) showQuestion();
          else showScore();
        });
        choicesEl.appendChild(button);
      });
    }

    function showScore() {
      progressEl.textContent = "Done";
      promptEl.textContent = "Quiz complete";
      choicesEl.replaceChildren();
      resultEl.textContent = "You scored " + score + " out of " + questions.length + ".";
      restartBtn.style.display = "inline-block";
    }

    restartBtn.addEventListener("click", function () {
      index = 0;
      score = 0;
      showQuestion();
    });

    showQuestion();
  </script>
</body>
</html>

One question at a time

Clearing the choice box with replaceChildren removes the old buttons and their listeners. That is simpler than disabling every button after a click. The next question gets a fresh set.

Do not show the correct answer in the result line for this project. The job is a score, not a review sheet. A practice task can add a missed-question list if you want that later.

Common mistakes

  • Comparing the button label to the answer string. Two choices that share a word would collide. Use the index.
  • Incrementing index before reading questions[index]. You would skip the first item.
  • Leaving old buttons in the box. Clicks would fire on a previous question and double-count.
  • Using innerHTML to inject choice text. A quote in the prompt would break the markup. Use textContent.
  • Hard-coding "Question 1 of 4" in HTML and never updating it. Read questions.length.

Practice tasks

  1. Add a fifth question about localStorage. Keep the same object shape.
  2. After each click, briefly show Correct or Miss before advancing. Use setTimeout for 700ms.
  3. List the missed prompts under the score. Preview at /javascript/try.

FAQ: JavaScript Project: Quiz

Common questions about this page.

What is the StudyGrid JavaScript tutorial?

The StudyGrid JavaScript tutorial is a full beginner track: variables, functions, arrays, if/else, the DOM, events, storage, and fetch. Each chapter has copy-and-run examples.

Should I run javascript quiz project examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn javascript quiz project in this JavaScript JavaScript lesson (JavaScript Project: Quiz).

Is the JavaScript editor the same as Try Python?

No. Try JavaScript is a live page plus a console at /javascript/try. Try Python stays at /try. JavaScript lessons never open the Python editor.

Do I need to install anything to learn JavaScript?

No. Open a chapter, click Try it in JavaScript, and the page and console update in the browser.

Where should I start the JavaScript tutorial?

Start at JavaScript Intro, then Where To, Output, and Syntax. After variables and functions, continue to the DOM and events. Use Next at the bottom of each chapter.

Is the JavaScript tutorial free?

Yes. The JavaScript studio on StudyGrid (studygrid.in) is free: dashboard, chapters, and the live editor.