20 JavaScript Coding Exercises to Build Real Skills

Whether you’re just starting your JavaScript journey or teaching others through workshops, classrooms, or self-paced learning, hands-on practice is the fastest way to build confidence.

This guide contains 20 beginner-to-intermediate JavaScript exercises, each with:

  • 🎯 Learning objectives
  • 🧪 A practical challenge
  • 💡 Full code solution
  • 📘 Clear explanation of how it all works

These exercises help learners understand not just what to type, but why the code behaves the way it does—core to the Vibe Learning methodology.

Let’s dive in.

🔢 Exercises 1–10 — Core JavaScript Foundations


1. Sum of Two Numbers

Objective: Variables, number conversion, output
Ask the user for two numbers and display their sum.

const num1 = Number(prompt("Enter first number:"));
const num2 = Number(prompt("Enter second number:"));
alert("The sum is: " + (num1 + num2));

Why it works:
prompt() returns a string, so Number() converts it. The numbers are added, and the result is shown with alert().


2. Even or Odd?

Objective: Conditionals, modulo operator

const value = Number(prompt("Enter a number:"));
if (value % 2 === 0) console.log("Even");
else console.log("Odd");

Why it works: % 2 gives the remainder—0 means even.


3. Countdown

Objective: Loops, backwards iteration

const n = Number(prompt("Enter a number:"));
for (let i = n; i >= 1; i--) {
  console.log(i);
}

Why it works:
A for loop counts down until it reaches 1.


4. Maximum of an Array

Objective: Arrays, tracking max values

const nums = [3, 17, 9, 42, 5];
let max = nums[0];

for (let i = 1; i < nums.length; i++) {
  if (nums[i] > max) max = nums[i];
}

console.log(max);

5. Greeting Function

Objective: Defining and calling functions

function greet(name) {
  console.log("Hello, " + name);
}

greet("Lars");

6. Change Page Text (DOM)

Objective: DOM selection & modification

const heading = document.getElementById("title");
heading.textContent = "Updated via JavaScript!";

7. Button Click Counter

Objective: Events, state management

let count = 0;
button.addEventListener("click", () => {
  count++;
  countSpan.textContent = count;
});

8. Shopping Cart Total

Objective: Objects, arrays, totals

const cart = [
  { name: "Book", price: 12.99 },
  { name: "Headphones", price: 29.99 }
];

let total = 0;
for (const item of cart) total += item.price;
console.log(total);

9. Convert Celsius to Fahrenheit (map)

Objective: Higher-order functions

const c = [0, 10, 20];
const f = c.map(n => n * 9/5 + 32);
console.log(f);

10. Simple Timer

Objective: setInterval, clearInterval

let secs = 0;
const timer = setInterval(() => {
  console.log(secs++);
  if (secs > 10) clearInterval(timer);
}, 1000);

💡 Exercises 11–20 — Intermediate JavaScript & DOM Skills

11. Reverse a String (Strings & Loops)

Learning Objectives

  • Work with strings and indices
  • Use a for loop to build a new string
  • Understand that strings are iterable

Task

Ask the user for a word and output the word reversed.

Sample Solution

const input = prompt("Enter a word to reverse:");
let reversed = "";

for (let i = input.length - 1; i >= 0; i--) {
  reversed += input[i];
}

console.log("Original:", input);
console.log("Reversed:", reversed);

Explanation

  • input.length - 1 gives the index of the last character.
  • The loop counts down to 0, adding each character to reversed.
  • reversed += input[i]; builds the new string one character at a time.

12. Word Counter (Strings & Split)

Learning Objectives

  • Use .trim() and .split()
  • Handle multiple spaces between words
  • Process user text input

Task

Ask the user to paste a sentence or paragraph and show how many words it has.

Sample Solution

const text = prompt("Paste a sentence or paragraph:") || "";

const trimmed = text.trim();

let wordCount = 0;

if (trimmed.length > 0) {
  const words = trimmed.split(/\s+/); // split on any whitespace
  wordCount = words.length;
}

console.log("Text:", text);
console.log("Word count:", wordCount);

Explanation

  • trim() removes extra spaces at the start and end.
  • split(/\s+/) splits on one or more whitespace characters (spaces, tabs, newlines).
  • If the trimmed text is empty, the count stays 0. Otherwise we count the words array length.

13. Number Guessing Game (Random & Loops)

Learning Objectives

  • Use Math.random() and Math.floor()
  • Implement a loop that keeps asking until correct
  • Give feedback (“too high/low”)

Task

Generate a secret number between 1 and 20. Let the user guess until correct, telling them if each guess is too high or too low.

Sample Solution

const secret = Math.floor(Math.random() * 20) + 1;
let guess;
let attempts = 0;

while (guess !== secret) {
  guess = Number(prompt("Guess a number between 1 and 20:"));
  attempts++;

  if (isNaN(guess)) {
    alert("Please enter a valid number.");
  } else if (guess < secret) {
    alert("Too low! Try again.");
  } else if (guess > secret) {
    alert("Too high! Try again.");
  } else {
    alert("Correct! The number was " + secret + ". Attempts: " + attempts);
  }
}

Explanation

  • Math.random() * 20 gives a number from 0 up to (but not including) 20.
  • Math.floor(...)+1 shifts it into the range 1–20.
  • The while loop runs until guess === secret.
  • We count attempts and give feedback after each guess.

14. Filter Even Numbers (Array Filter)

Learning Objectives

  • Use Array.prototype.filter
  • Understand callback functions returning true or false
  • Build new arrays based on conditions

Task

Given an array of numbers, create a new array containing only even numbers.

Sample Solution

const numbers = [1, 4, 7, 10, 13, 16, 19, 22];

const evens = numbers.filter(function (n) {
  return n % 2 === 0;
});

// Or: const evens = numbers.filter(n => n % 2 === 0);

console.log("Original:", numbers);
console.log("Even numbers:", evens);

Explanation

  • .filter(callback) runs callback for each element.
  • If callback returns true, the element is kept; if false, it’s dropped.
  • n % 2 === 0 is true for even numbers, so we keep those.

15. Sum with reduce (Array Reduce)

Learning Objectives

  • Use Array.prototype.reduce
  • Understand accumulator and current value
  • Replace loop-based summing with functional style

Task

Using the same numbers array, compute the total sum with .reduce.

Sample Solution

const numbers = [5, 10, 15, 20];

const total = numbers.reduce(function (acc, current) {
  return acc + current;
}, 0); // 0 is the starting value

console.log("Numbers:", numbers);
console.log("Total:", total);

Explanation

  • .reduce(callback, initialValue) starts with acc = initialValue.
  • For each element:
    • acc is the accumulated result so far.
    • current is the current array item.
  • We return acc + current each time, so by the end acc holds the sum.

16. Unique Values (Sets & Arrays)

Learning Objectives

  • Use Set to remove duplicates
  • Convert between Set and Array
  • Work with repeated values

Task

From an array with duplicate numbers, create a new array of unique values.

Sample Solution

const withDuplicates = [1, 2, 2, 3, 4, 4, 4, 5];

const uniqueArray = Array.from(new Set(withDuplicates));

console.log("With duplicates:", withDuplicates);
console.log("Unique values:", uniqueArray);

Explanation

  • new Set(array) keeps only unique values (no duplicates).
  • Array.from(set) converts the Set back into a regular array.
  • The order of first appearance is preserved.

17. Build a Dynamic List (DOM & Loops)

Use a simple HTML file and link a script.

Learning Objectives

  • Create elements with document.createElement
  • Append children to the DOM
  • Generate lists from arrays

HTML Setup

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>TODO List</title>
  </head>
  <body>
    <h1>Tasks</h1>
    <ul id="taskList"></ul>
    <script src="script.js"></script>
  </body>
</html>

script.js Sample Solution

const tasks = ["Learn JavaScript", "Practice DOM", "Build a project"];

const list = document.getElementById("taskList");

for (let i = 0; i < tasks.length; i++) {
  const li = document.createElement("li");
  li.textContent = tasks[i];
  list.appendChild(li);
}

Explanation

  • tasks holds text for each list item.
  • document.getElementById("taskList") selects the <ul>.
  • For each task:
    • We create an <li> element.
    • Set its textContent.
    • appendChild() attaches it to the <ul>.

18. Show / Hide Details (DOM Events & Class Toggling)

Learning Objectives

  • Respond to button clicks
  • Show/hide elements using CSS classes
  • Use classList.toggle

HTML Setup

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Show / Hide</title>
    <style>
      .hidden {
        display: none;
      }
    </style>
  </head>
  <body>
    <button id="toggleBtn">Show details</button>
    <p id="details" class="hidden">
      These are some extra details about the topic.
    </p>

    <script src="script.js"></script>
  </body>
</html>

script.js Sample Solution

const button = document.getElementById("toggleBtn");
const details = document.getElementById("details");

button.addEventListener("click", function () {
  details.classList.toggle("hidden");

  if (details.classList.contains("hidden")) {
    button.textContent = "Show details";
  } else {
    button.textContent = "Hide details";
  }
});

Explanation

  • .hidden in CSS hides an element.
  • classList.toggle("hidden") adds the class if it’s missing, or removes it if it’s present.
  • After toggling, we check if the element is now hidden to update the button text.

19. Simple Form Validation (DOM & Basic Validation)

Learning Objectives

  • Hook into form submission with submit event
  • Prevent default form behavior
  • Validate required fields in JavaScript

HTML Setup

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Signup Form</title>
  </head>
  <body>
    <form id="signupForm">
      <label>
        Email:
        <input type="email" id="email" />
      </label>
      <br />
      <label>
        Password:
        <input type="password" id="password" />
      </label>
      <br />
      <button type="submit">Sign Up</button>
    </form>

    <p id="message"></p>

    <script src="script.js"></script>
  </body>
</html>

script.js Sample Solution

const form = document.getElementById("signupForm");
const emailInput = document.getElementById("email");
const passwordInput = document.getElementById("password");
const message = document.getElementById("message");

form.addEventListener("submit", function (event) {
  event.preventDefault(); // stop actual form submission

  const email = emailInput.value.trim();
  const password = passwordInput.value.trim();

  if (!email || !password) {
    message.textContent = "Please fill in both email and password.";
    return;
  }

  if (password.length < 6) {
    message.textContent = "Password must be at least 6 characters.";
    return;
  }

  message.textContent = "Signup successful (demo)!";
});

Explanation

  • The submit event runs when the user clicks the button or presses Enter.
  • event.preventDefault() stops the page from reloading.
  • We read .value from the inputs and .trim() spaces.
  • Simple checks: both fields required, password length.
  • The message paragraph gives feedback instead of sending data anywhere.

20. Persistent Click Counter (localStorage)

Learning Objectives

  • Use localStorage to store data in the browser
  • Convert numbers to/from strings when saving/loading
  • Keep state across page refreshes

HTML Setup

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Persistent Counter</title>
  </head>
  <body>
    <button id="countBtn">Click me</button>
    <p>Total clicks (saved in browser): <span id="total">0</span></p>

    <script src="script.js"></script>
  </body>
</html>

script.js Sample Solution

const button = document.getElementById("countBtn");
const totalSpan = document.getElementById("total");

// Load saved count or default to 0
let total = Number(localStorage.getItem("clickTotal")) || 0;
totalSpan.textContent = total;

button.addEventListener("click", function () {
  total++;
  totalSpan.textContent = total;
  localStorage.setItem("clickTotal", String(total));
});

Explanation

  • localStorage.getItem("clickTotal") returns a string or null if missing.
  • Number(...) || 0 converts it or falls back to 0.
  • Every click:
    • total increases.
    • We update the <span>.
    • We save the new value with localStorage.setItem.
  • Refresh the page — the count stays, because it’s stored in the browser.