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
forloop 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 - 1gives the index of the last character.- The loop counts down to
0, adding each character toreversed. 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 thewordsarray length.
13. Number Guessing Game (Random & Loops)
Learning Objectives
- Use
Math.random()andMath.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() * 20gives a number from0up to (but not including)20.Math.floor(...)+1shifts it into the range1–20.- The
whileloop runs untilguess === 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
trueorfalse - 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)runscallbackfor each element.- If
callbackreturnstrue, the element is kept; iffalse, it’s dropped. n % 2 === 0istruefor 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 withacc = initialValue.- For each element:
accis the accumulated result so far.currentis the current array item.
- We return
acc + currenteach time, so by the endaccholds the sum.
16. Unique Values (Sets & Arrays)
Learning Objectives
- Use
Setto remove duplicates - Convert between
SetandArray - 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 theSetback 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
tasksholds 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>.
- We create an
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
.hiddenin 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
submitevent - 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
submitevent runs when the user clicks the button or presses Enter. event.preventDefault()stops the page from reloading.- We read
.valuefrom 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
localStorageto 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 ornullif missing.Number(...) || 0converts it or falls back to0.- Every click:
totalincreases.- 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.