How I Approach JavaScript Problems When I Don't Know Where to Start

One thing I struggled with when learning JavaScript was knowing what to do when I understood the syntax but could not solve a problem.

I could understand variables, loops, functions and arrays when someone explained them. But when I was given a blank editor and a problem to solve, I often had no idea where to begin.

Over time, I found that the problem was not always JavaScript itself.

I was trying to write the solution before understanding the problem.

Here is the process I now use when I get stuck.

1. Read the problem without writing code

Suppose the problem says:

Write a function that receives an array of numbers and returns the numbers that appear more than once.

My first instinct might be to start writing a loop.

Instead, I stop and create a simple example.

const numbers = [4, 7, 4, 9, 2, 7, 7];

What should the result be?

[4, 7]

Now the problem is much clearer.

I need to identify values that occur more than once.

That is easier to reason about than simply staring at the original question.

2. Work through the example manually

Before writing JavaScript, I try to solve the problem with a pen and paper.

For the array:

[4, 7, 4, 9, 2, 7, 7]

I can count the values:

4 appears 2 times
7 appears 3 times
9 appears 1 time
2 appears 1 time

Now I know that I need some way to keep track of how many times each value appears.

That immediately suggests an object could be useful.

3. Break the problem into smaller tasks

Instead of thinking:

“How do I solve this?”

I ask:

“What are the individual things I need to do?”

In this example:

  1. Go through every number.
  2. Keep track of how often each number appears.
  3. Find the numbers whose count is greater than one.
  4. Return those numbers.

Now I have a plan.

The code becomes much easier to write because I am no longer trying to solve the entire problem at once.

4. Write the simplest version first

I would start with something like this:

function findDuplicates(numbers) {
  const counts = {};

  for (const number of numbers) {
    if (counts[number]) {
      counts[number]++;
    } else {
      counts[number] = 1;
    }
  }

  const duplicates = [];

  for (const number in counts) {
    if (counts[number] > 1) {
      duplicates.push(Number(number));
    }
  }

  return duplicates;
}

Then test it:

console.log(
  findDuplicates([4, 7, 4, 9, 2, 7, 7])
);

The expected result is:

[4, 7]

The solution is not necessarily the shortest or most clever solution.

That is fine.

When learning, I would rather have a solution I understand than a one-line solution I copied from somewhere.

5. Test more than one example

Getting the expected result once does not necessarily mean the function is correct.

I would test several cases.

findDuplicates([1, 2, 3, 4]);

Expected:

[]

Another case:

findDuplicates([5, 5, 5, 5]);

Expected:

[5]

And an empty array:

findDuplicates([]);

Expected:

[]

Testing different inputs forces you to think about edge cases.

This is something I did not pay enough attention to when I first started learning.

I often tested the exact example from the exercise and assumed the function was finished.

6. Use console.log when you are confused

When a solution does not work, I try not to immediately rewrite everything.

Instead, I inspect what the program is doing.

For example:

function findDuplicates(numbers) {
  const counts = {};

  for (const number of numbers) {
    if (counts[number]) {
      counts[number]++;
    } else {
      counts[number] = 1;
    }

    console.log(number, counts);
  }

  return counts;
}

The output lets me see how counts changes after every iteration.

This can reveal mistakes that are difficult to spot by simply reading the code.

For beginners, console.log() is more than a way to print a final answer.

It is a debugging tool.

7. Do not change five things at once

This is another habit that helped me.

If something is broken, change one thing and test again.

For example, if this does not work:

if (counts[number] > 1) {
  duplicates.push(number);
}

I would inspect counts[number].

Maybe the problem is that the count has not been created correctly.

Maybe the value is a string instead of a number.

Maybe the loop is not processing all the values.

The goal is to find the exact point where my assumption differs from what the program is doing.

8. Learn array methods by solving problems

I used to learn methods such as map(), filter() and reduce() by memorising examples.

That helped with syntax, but it did not help much when I faced a new problem.

A better approach is to start with a requirement.

For example:

const numbers = [3, 8, 12, 5, 20];

Requirement:

“Return only numbers greater than 10.”

I can use:

const result = numbers.filter(number => number > 10);

Then change the requirement:

“Return each number multiplied by two.”

const result = numbers.map(number => number * 2);

Then:

“Calculate the total.”

const result = numbers.reduce(
  (total, number) => total + number,
  0
);

The important thing is learning to recognise the type of operation you need.

You are not trying to memorise three methods.

You are learning to recognise three different problems.

9. Try the problem again without looking at your old solution

This is probably one of the most useful things I have found.

After solving a problem, wait a day or two and try it again without looking at the solution.

If you can solve it again, you probably understood the concept.

If you cannot, that is useful information too.

It tells you that you may have remembered the solution without fully understanding why it worked.

For example, if you learned how to remove duplicates using Set:

const unique = [...new Set(numbers)];

Try solving the same problem without Set.

That forces you to think about what “unique” actually means and how you would implement it yourself.

10. Make small variations

Once I can solve a problem, I like to change the requirements.

Suppose the original problem is:

“Find the largest number.”

const numbers = [12, 5, 19, 7, 3];

Then I might change it to:

“Find the smallest number.”

Then:

“Find both the largest and smallest.”

Then:

“Find the second largest.”

Then:

“Find the largest number without using Math.max().”

Each variation requires slightly different thinking.

This is where I feel that real programming ability starts developing.

What I do when I completely understand nothing

Sometimes a problem is simply beyond my current level.

In that situation, I do not think there is anything wrong with looking for help.

But I try to look for an explanation rather than immediately copying the final code.

For example, if I do not understand reduce(), I would first learn what an accumulator is and work through a very small example.

Then I would return to the original problem.

The same applies to promises, closures, destructuring, recursion or any other concept that feels unfamiliar.

Understanding the missing concept is usually more useful than memorising the solution to one exercise.

Practice is different from reading

One thing that has become obvious to me is that reading JavaScript code can create a false sense of progress.

I can read this:

const adults = users.filter(user => user.age >= 18);

and understand exactly what it does.

But that does not necessarily mean I can write it from memory when given a problem.

There is a difference between recognising code and producing code.

That is why I think solving small JavaScript exercises is so useful.

You have to start with a blank space and decide what to write.

For anyone who wants a structured place to do that kind of JavaScript practice, there are platforms that provide exercises with immediate feedback. I have found that this type of practice can be useful when you want to spend more time writing code and less time searching for what to practise next.

A simple routine for beginners

If I were starting JavaScript again, I would keep the practice routine simple.

I would spend some time learning one concept.

Then I would solve two or three small problems using it.

After solving them, I would change the requirements and solve them again.

Finally, I would review the mistakes I made.

For example, if I were learning arrays:

Day 1
Find the largest number
Find the smallest number

Day 2
Remove duplicates
Find duplicate values

Day 3
Use filter()
Use map()

Day 4
Use reduce()
Combine multiple array methods

Day 5
Solve the same problems again without looking at the answers

The exact schedule does not matter very much.

What matters is spending time actually writing JavaScript.

You do not need to know everything before building projects

Another mistake I made was thinking I needed to finish learning JavaScript before starting projects.

That point never really arrives.

There is always another method, API, browser feature or language concept to learn.

A small project can actually show you what you need to learn next.

You might start a simple task manager and realise you need to understand DOM events.

Then you discover local storage.

Then you need to work with arrays of objects.

Then you need to handle form validation.

Each problem gives you a reason to learn the next concept.

That is much more practical than trying to learn every JavaScript feature in advance.

Final thought

When I get stuck on a JavaScript problem now, I try not to ask:

“What syntax am I missing?”

I ask:

“What exactly is the problem asking me to do?”

Then I create a small example, solve it manually, break it into smaller steps and write the simplest solution I can.

If it does not work, I debug it.

If it works, I change the requirements and try again.

That process has been much more useful to me than trying to memorise every JavaScript method.

I am curious how other people approach this.

When you get stuck on a JavaScript problem, what is the first thing you usually do?

3 Likes

Working through an example on paper before touching code makes a huge difference. When I get stuck on array logic, I usually write down the input and the exact intermediate steps before picking a loop or array method. Doing that step first keeps me from rewriting functions halfway through.

Working through an example by hand is a reliable way to get unstuck. When breaking down problems, writing out inputs, outputs, and edge cases like empty arrays or duplicate values before writing code makes the logic much easier to structure.

For debugging, isolating the smallest failing step saves time. If a loop or transformation gives an unexpected result, testing a single item through the steps or logging intermediate values usually shows where the logic broke.