When learning JavaScript, it is easy to spend a lot of time memorising syntax.
You learn how to declare variables, write functions, use loops and work with arrays. Then you learn map(), filter(), reduce(), destructuring and other features.
Everything seems clear while you are following an example.
Then you open a blank editor and receive a simple problem to solve.
Suddenly, knowing the syntax does not feel like enough.
That is because programming is not only about remembering language features. You also need to learn how to break a problem into smaller pieces, decide what information you need and turn your idea into working code.
One of the best ways to develop that ability is through small, focused problems.
Here are ten JavaScript problems that can help you practise those skills.
1. Reverse a string
Start with something simple.
Create a function that receives a string and returns it backwards.
function reverseString(text) {
// Write your solution here
}
console.log(reverseString("developer"));
// "repoleved"
A simple solution is:
function reverseString(text) {
return text.split("").reverse().join("");
}
But do not stop there.
Try solving it without reverse().
function reverseString(text) {
let result = "";
for (let i = text.length - 1; i >= 0; i--) {
result += text[i];
}
return result;
}
The second version is longer, but it makes you think about string positions, loops and how a result is constructed.
That is the real value of the exercise.
2. Find the largest number
Consider this array:
const numbers = [14, 7, 29, 11, 42, 18];
Write a function that returns the largest number.
function findLargest(numbers) {
// Write your solution here
}
One approach is:
function findLargest(numbers) {
let largest = numbers[0];
for (const number of numbers) {
if (number > largest) {
largest = number;
}
}
return largest;
}
The important idea is the variable largest.
You begin with an assumption and replace it whenever you find a bigger value.
This pattern appears in many programming problems.
Once you understand it, try changing the problem.
Find the smallest number.
Find both the largest and smallest.
Find the second largest number.
Find the largest number without using Math.max().
Small variations force you to understand the original solution instead of simply remembering it.
3. Count the vowels in a string
Now combine strings, loops and conditions.
function countVowels(text) {
// Write your solution here
}
console.log(countVowels("JavaScript"));
// 3
One solution is:
function countVowels(text) {
const vowels = "aeiou";
let count = 0;
for (const character of text.toLowerCase()) {
if (vowels.includes(character)) {
count++;
}
}
return count;
}
There are several useful concepts here.
The text is converted to lowercase so uppercase vowels do not need separate handling.
The string is iterated character by character.
includes() checks whether the current character is a vowel.
The counter increases whenever the condition is true.
Try modifying the problem so that the function returns the number of each vowel instead.
*For example:
*
{
a: 2,
e: 1,
i: 0,
o: 0,
u: 1
}
That small change introduces a completely different data structure.
4. Remove duplicate values
Consider this array:
const numbers = [3, 7, 3, 9, 7, 4, 9, 2];
Create a function that returns each value only once.
The expected result is:
[3, 7, 9, 4, 2]
A modern solution is:
function removeDuplicates(numbers) {
return [...new Set(numbers)];
}
But try solving the same problem without Set.
function removeDuplicates(numbers) {
const result = [];
for (const number of numbers) {
if (!result.includes(number)) {
result.push(number);
}
}
return result;
}
The second solution gives you more practice with arrays, loops and conditions.
It also raises an important question.
What exactly does it mean for a value to be duplicated?
Once you start asking questions like that, you move from memorising code toward understanding problems.
5. Count how many times each value appears
Now take this array:
const colors = [
"red",
"blue",
"red",
"green",
"blue",
"red"
];
Create an object containing the number of times each color appears.
Expected result:
{
red: 3,
blue: 2,
green: 1
}
One solution is:
function countValues(values) {
const counts = {};
for (const value of values) {
if (counts[value]) {
counts[value]++;
} else {
counts[value] = 1;
}
}
return counts;
}
This is a useful pattern because real applications frequently need to count or group information.
You might count categories, page visits, search terms, votes or transaction types.
The exercise is simple, but the underlying idea is useful far beyond a beginner exercise.
6. Filter an array of objects
Most real applications work with structured data rather than arrays of simple numbers.
Consider:
const products = [
{ name: "Keyboard", price: 45 },
{ name: "Monitor", price: 180 },
{ name: "Mouse", price: 25 },
{ name: "Headphones", price: 80 }
];
Return only products costing more than 50.
const expensiveProducts = products.filter(product => {
return product.price > 50;
});
console.log(expensiveProducts);
Now change the requirement.
Return only products under 50.
Then return products whose name contains the letter o.
Then return products within a particular price range.
The goal is to become comfortable reading the structure of an object and writing conditions against its properties.
7. Transform an array with map()
Now use the same product data.
Instead of filtering products, return an array containing only their names.
const productNames = products.map(product => {
return product.name;
});
console.log(productNames);
The result is:
[
"Keyboard",
"Monitor",
"Mouse",
"Headphones"
]
The distinction between filter() and map() is worth understanding.
filter() decides which items remain.
map() transforms each item into something else.
Try creating a new array where every product has a discounted price.
const discountedProducts = products.map(product => {
return {
...product,
price: product.price * 0.9
};
});
This is a small example of transforming application data without modifying the original objects.
8. Calculate a total with reduce()
reduce() is one of those JavaScript methods that can look confusing when you first encounter it.
Start with something simple:
const prices = [10, 25, 15, 30];
Calculate the total:
const total = prices.reduce((sum, price) => {
return sum + price;
}, 0);
console.log(total);
// 80
The easiest way to understand this is to follow the accumulator.
0 + 10 = 10
10 + 25 = 35
35 + 15 = 50
50 + 30 = 80
Now make the problem more realistic.
const cart = [
{ name: "Book", price: 15 },
{ name: "Notebook", price: 8 },
{ name: "Pen", price: 3 }
];
Calculate the total cost:
function calculateTotal(cart) {
return cart.reduce((total, product) => {
return total + product.price;
}, 0);
}
Once you understand this example, try calculating an average instead.
Then calculate the total quantity of items.
Then find the most expensive item.
Changing the requirement is where the practice becomes useful.
9. Find an object in an array
Suppose you have a list of users:
const users = [
{ id: 101, name: "Alex" },
{ id: 102, name: "Maria" },
{ id: 103, name: "Daniel" }
];
Write a function that finds a user by ID.
function findUser(users, id) {
return users.find(user => user.id === id);
}
console.log(findUser(users, 102));
The result is:
{
id: 102,
name: "Maria"
}
Now change the requirement.
Find a user by name.
Find the first user over a certain age.
Return undefined when no match exists.
Then try the same problems using filter().
This will help you understand why find() and filter() are different.
find() returns the first matching item.
filter() returns an array containing all matching items.
These distinctions become important when working with real application data.
10. Connect JavaScript to the DOM
So far, the problems have focused mainly on JavaScript logic.
Now connect that logic to the browser.
Imagine a simple counter:
0
JavaScript can respond to the click:
const countElement = document.querySelector("#count");
const increaseLink = document.querySelector("#increase");
let count = 0;
increaseLink.addEventListener("click", event => {
event.preventDefault();
count++;
countElement.textContent = count;
});
This tiny example combines several concepts.
You select elements from the DOM.
You store state in a variable.
You listen for an event.
You update the page.
Now make the exercise harder.
Add a reset action.
Add a decrease action.
Prevent the counter from going below zero.
Display a message when the counter reaches ten.
Save the value to local storage.
Each change gives you another programming problem to solve.
The important part is what you do when you get stuck
A lot of JavaScript learning happens when the code does not work.
Suppose you write:
const result = numbers.filter(number => number > 10);
but the result is not what you expected.
Do not immediately search for another solution.
First inspect the input:
console.log(numbers);
Then inspect the result:
console.log(result);
If necessary, inspect each value:
numbers.forEach(number => {
console.log(number);
});
This helps you identify whether the problem is with your data, your condition or your assumption.
Debugging should not be treated as something you learn after you become good at programming.
Debugging is part of becoming good at programming.
Try problems without looking at the answer
One of the easiest ways to reduce the value of an exercise is to look at the solution too quickly.
If you read a solution and think, "That makes sense," you have learned something.
But you have not necessarily learned how to produce the solution yourself.
Try this instead.
Read the problem.
Create a small example.
Solve the example manually.
Write down the steps.
Then start coding.
If you get stuck, identify exactly what you do not understand.
Only then look for help.
After reading the solution, close it and write your own version.
That last step matters.
It forces you to reconstruct the idea instead of simply copying the code.
Build a small practice routine
You do not need to solve fifty JavaScript problems every day.
A small and consistent routine is enough.
For example:
Monday
Strings and loops
Tuesday
Arrays and conditions
Wednesday
Objects and data
Thursday
map(), filter() and reduce()
Friday
DOM and events
Spend twenty or thirty minutes solving problems.
Then spend a few minutes reviewing your mistakes.
If you want a structured environment for this kind of practice, JS Exercises provides browser-based JavaScript exercises with tests and guided learning material. It can be useful when you want to practise writing code rather than simply reading another tutorial.
The specific platform is less important than the habit.
You need regular opportunities to start with a problem and produce your own solution.
Turn exercises into projects
Individual exercises teach individual concepts.
Projects teach you how those concepts work together.
Once you are comfortable with arrays, objects, functions and DOM manipulation, try building something small.
A habit tracker is a good example.
You might need an array to store habits.
Objects can represent individual habits.
map() can help display data.
filter() can remove completed or deleted items.
DOM events can respond to user actions.
Local storage can preserve the data between browser sessions.
Suddenly, several concepts you learned separately become part of one application.
The project does not need to be impressive.
It needs to make you think.
Do not worry about memorising every JavaScript method
JavaScript has a large ecosystem.
There will always be methods, APIs and browser features that you have not used before.
Even experienced developers look things up.
The important skill is understanding the problem well enough to know what kind of solution you need.
If you know that you need to select matching items from an array, you can look up filter() if you forget the exact syntax.
If you know that you need to transform every item, you can look up map().
If you need to combine values into one result, you can investigate reduce().
Understanding the purpose is more valuable than memorising every character.
Final thoughts
JavaScript becomes easier when you spend less time trying to memorise syntax and more time solving problems.
Start with something small.
Write the problem in your own words.
Create a simple example.
Break it into steps.
Write a first solution.
Run it.
Debug it.
Then change the requirements and try again.
That process develops something that tutorials alone cannot provide.
You start building the ability to look at a new programming problem and think about how you might solve it.
That is the skill that eventually makes JavaScript feel less like a collection of syntax rules and more like a tool you can actually use.
Top comments (0)