Common mistakes with loops

Loops are like the backbone of any programming language, and JavaScript is no exception. They allow you to automate repetitive tasks, just like how a busy Indian household might automate certain chores during a grand festival or wedding. However, just like in any large event, things can go wrong. Mistakes can happen, and if you’re not careful, your loops might go "crazy", leaving you stuck or causing unexpected issues in your code.
Let's learn what NOT to do in this article so that we can do the right things much better.
Off-by-One Errors
Off-by-one errors are like that one Diwali light that just won’t turn on, no matter what you do. You think you’ve got everything set up perfectly, but somehow, something’s missing. These errors typically occur when your loop iterates one extra time or one less than needed.
Why does this happen? It is very simple actually, to understand let's take the below code snippet.
let tasks = ["Buy Sweets", "Decorate House", "Make Rangoli", "Light Diyas", "Prepare Feasts"];
for (let i = 0; i <= tasks.length; i++) {
console.log(`Task ${i + 1}: ${tasks[i]}`);
}
Can you spot the mistake? The loop runs one extra time because of the <=
condition, which leads to undefined
being printed for the last task.

Hence be careful while you write that for
loop.
Corrected version:
let tasks = ["Buy Sweets", "Decorate House", "Make Rangoli", "Light Diyas", "Prepare Feasts"];
for (let i = 0; i <= tasks.length - 1; i++) {
console.log(`Task ${i + 1}: ${tasks[i]}`);
}
Always double-check your loop conditions. If you’re iterating over an array, remember that array indices start at 0 and end at length - 1
. A simple change from <=
to <
can save you from this common mistake.
Infinite Loops
Infinite loops are like that one relative who just won’t stop talking during a family gathering. No matter what you do, you can’t escape, and before you know it, hours have passed. In coding, an infinite loop can cause your program to freeze or crash, leaving you stuck with no way out. It keeps consuming the resources and your app can start hanging or become unresponsive very quickly! It is the worst kind of error that we as developers could make.
let diyasToLight = 5;
while (diyasToLight > 0) {
console.log(`Lighting diya number ${diyasToLight}`);
// Forgot to decrement the counter
}
In this code, the loop keeps running forever because diyasToLight
is never decremented, so the condition diyasToLight > 0
always holds true.
Corrected code:
let diyasToLight = 5;
while (diyasToLight > 0) {
console.log(`Lighting diya number ${diyasToLight}`);
diyasToLight--; // Decrementing the counter to avoid infinite loop
}
Now this code will run only 5 times. i.e. 5, 4 ,3, 2 and 1. and then the condition diyasToLight > 0
does not become true Hence the loop breaks away.
Modifying the Loop Counter Inside the Loop
Changing the loop counter inside the loop is like rearranging your Diwali shopping list while you’re already in the store. You’ll end up confused, and so will your code. This mistake can lead to unexpected behavior, such as skipping tasks or performing them out of order.
If you modify the loop counter within the loop body, it can disrupt the loop’s flow. Here’s an example:
let tasks = ["Buy Sweets", "Decorate House", "Make Rangoli", "Light Diyas", "Prepare Feasts"];
for (let i = 0; i < tasks.length; i++) {
console.log(`Task ${i + 1}: ${tasks[i]}`);
if (tasks[i] === "Decorate House") {
i++; // Modifying loop counter inside the loop
}
}

In this code, modifying i
inside the loop causes the loop to skip over the next task, leading to missed preparations.
Let's look at the fixed code now to understand how we should do it correctly.
let tasks = ["Buy Sweets", "Decorate House", "Make Rangoli", "Light Diyas", "Prepare Feasts"];
for (let i = 0; i < tasks.length; i++) {
console.log(`Task ${i + 1}: ${tasks[i]}`);
if (tasks[i] === "Decorate House") {
// i++; // Removed to prevent skipping the next task
}
}
By avoiding modifications to the loop counter, you ensure that no tasks are skipped, and your Diwali preparations go smoothly.
Misplacing the Increment/Decrement Step
Forgetting to place the increment or decrement step in the right place is like forgetting to add sugar to your Diwali sweets. Everything might seem fine until you take a bite—or, in the case of loops, until your loop doesn’t behave as expected.
If you place the increment or decrement step incorrectly, your loop might not run as intended. Here’s an example
let tasks = ["Buy Sweets", "Decorate House", "Make Rangoli", "Light Diyas", "Prepare Feasts"];
for (let i = 0; i < tasks.length; ) {
console.log(`Task ${i + 1}: ${tasks[i]}`);
i++; // Increment step is inside the loop but not at the end
}
While this loop runs, placing the increment step inside the loop body can lead to confusion and is generally less readable.
Nested Loops (Time complexity issue )
Nested loops can be incredibly powerful, like organizing multiple Diwali celebrations at once. But they can also lead to unexpected problems if not handled carefully, much like trying to juggle too many tasks during the festival season.
Nested loops can quickly become complex and hard to manage, leading to performance issues or unexpected behavior. Let's see en example
let families = [
["Buy Sweets", "Decorate House"],
["Make Rangoli", "Light Diyas"],
["Prepare Feasts", "Distribute Gifts"]
];
for (let i = 0; i < families.length; i++) {
for (let j = 0; j < families[i].length; j++) {
console.log(`Task ${j + 1} for family ${i + 1}: ${families[i][j]}`);
}
}

While this loop works, it can quickly become difficult to manage if you add more layers or forget which loop controls which part of the process.
Hence it is better to keep things simple if there is no need of nested loops. If it can be done without nested loops, then avoid it at all costs, don't make things unnecessarily complicated.
When using nested loops, make sure you clearly understand the relationships between the loops. Comment your code, use descriptive variable names, and consider whether you can simplify the process, perhaps by breaking it into smaller functions or using methods like map
or forEach
.
Forgetting to reset variables
Forgetting to reset variables inside a loop is like forgetting to clean up after a Diwali party. You’ll end up with a mess, and things won’t work as expected the next time you try to use them.
If you’re using a variable to store data within a loop, forgetting to reset it can lead to unexpected results, no?
Let's check this example below:
let totalTasks = 0;
let families = [
["Buy Sweets", "Decorate House"],
["Make Rangoli", "Light Diyas"],
["Prepare Feasts", "Distribute Gifts"]
];
for (let i = 0; i < families.length; i++) {
let tasksDone = 0;
for (let j = 0; j < families[i].length; j++) {
tasksDone++;
}
totalTasks += tasksDone;
}
console.log(`Total tasks completed: ${totalTasks}`);

In this code, tasksDone
is correctly reset inside the loop, ensuring accurate counting. If you forget to reset it, the count will be incorrect.
Always check if your variables need to be reset inside a loop. If you’re using them to accumulate or track data, resetting them at the right place ensures your loop behaves as expected.
In this article, we’ve explored six common mistakes with loops, I hope you are clear with these concepts. There are many "innovative" ways to make more mistakes, but it is important to be careful not make such mistakes as this can lead to a lot of time being wasted debugging such errors.