Loops repeat a block of code. JavaScript offers the classic for, the modern for-of, for-in for object keys, and the while and do-while loops. Arrays also have built-in iterator methods like forEach, map, filter, and reduce that express what you want directly. This lesson covers all of them and the patterns you will use most often.
The classic for loop
for has three parts in parentheses: init, condition, and update. The body runs as long as the condition is true. Use this when you need the index, want to skip elements, or want fine control over the loop counter.
for (let i = 0; i < 5; i++) {
console.log(i);
}
// 0 1 2 3 4
const fruits = ["apple", "banana", "cherry"];
for (let i = 0; i < fruits.length; i++) {
console.log(`${i + 1}. ${fruits[i]}`);
}
// 1. apple
// 2. banana
// 3. cherry
for-of over iterables
for-of is the modern way to iterate any iterable: arrays, strings, Maps, Sets, generators, and more. The loop variable takes each value. Use the entry syntax to get both key and value from a Map.
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
console.log(fruit);
}
// String characters
for (const ch of "JavaScript") {
process.stdout.write(ch + " ");
}
// J a v a S c r i p t
// Map entries
const ages = new Map([["Asha", 28], ["Bala", 31]]);
for (const [name, age] of ages) {
console.log(`${name} is ${age}`);
}
for-in for object keys
for-in iterates the enumerable property keys of an object. It is designed for plain objects, not arrays. Use Object.keys, Object.values, or Object.entries when you want predictable array outputs.
const user = { name: "Asha", role: "admin", age: 28 };
for (const key in user) {
console.log(`${key} = ${user[key]}`);
}
// name = Asha
// role = admin
// age = 28
// Preferred: Object.entries for clean key-value access
for (const [key, value] of Object.entries(user)) {
console.log(`${key} = ${value}`);
}
while and do-while
while runs as long as a condition holds. do-while runs the body at least once and then checks the condition. Use break to exit the loop early and continue to skip to the next iteration.
let n = 1;
while (n <= 5) {
console.log(n);
n++;
}
// 1 2 3 4 5
let input;
do {
input = "ready"; // imagine this is user input
} while (input !== "quit");
Array iterator methods
Array methods express intent directly and are usually the right choice when you are transforming or inspecting an array. forEach just iterates. map returns a new array of the same length. filter returns a subset. reduce accumulates a single value. find returns the first match. some and every test a condition.
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const doubled = nums.map(n => n * 2);
const evens = nums.filter(n => n % 2 === 0);
const sum = nums.reduce((acc, n) => acc + n, 0);
const firstBig = nums.find(n => n > 5);
const hasEven = nums.some(n => n % 2 === 0);
const allPositive = nums.every(n => n > 0);
console.log(doubled); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
console.log(evens); // [2, 4, 6, 8, 10]
console.log(sum); // 55
console.log(firstBig); // 6
console.log(hasEven); // true
console.log(allPositive); // true
Summary
Use for-of to iterate iterables, for-in only for plain object keys, while for condition-driven loops, and the array methods (map, filter, reduce, find, some, every) to express transformations directly. The next lesson covers arrays in depth, including the mutating methods, sorting, and destructuring.
Common pitfalls in loops
The most common bug with the classic for loop is the off-by-one error. The most common bug with for-of is expecting it to work on a plain object; plain objects are not iterable. The most common bug with array iterator methods is forgetting to return the accumulator in reduce, which silently produces the wrong result. Finally, mixing forEach with await inside does not work the way you expect; forEach does not await its callback. Use for-of instead when you need to await inside a loop.
// WRONG: forEach does not await
async function loadAll(urls) {
const results = [];
urls.forEach(async (u) => {
results.push(await fetch(u));
});
return results; // may be empty
}
// RIGHT: for-of awaits each iteration
async function loadAll(urls) {
const results = [];
for (const u of urls) {
results.push(await fetch(u));
}
return results;
}
Performance tips
For numeric loops over a fixed count, the classic for is the fastest form because there is no callback overhead and no allocation of an iterator object. For arrays, for-of and array methods are usually fine; the engines optimize them. Cache the array length when you write a hot classic for loop, especially if the array is mutable and you do not want to re-read length on every iteration. Avoid reduce when a simple for loop is clearer; reduce is wonderful for expressing an accumulation but it is not always faster.
Comparison with Python
Python uses for item in iterable for the most common form, like JavaScript's for-of. Python's range-based for loop is the equivalent of JavaScript's classic for, but range returns an iterable rather than being part of the syntax. Python's enumerate gives you both the index and the value, like a manual classic for in JavaScript. Python's list comprehensions cover the same ground as map and filter combined. Python's break, continue, and while work the same way. The biggest practical difference is that Python's for always creates a new variable in the enclosing scope; JavaScript's for-of creates a new binding per iteration when you use let or const.