Skip to main content
Advertisement

3.2 Loops

What are Loops?

Loops execute the same or similar operations multiple times. JavaScript provides various loop constructs.


for Loop

The most basic loop, expressing initialization, condition, and increment in one line.

// Basic for loop
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}

// Reverse
for (let i = 4; i >= 0; i--) {
console.log(i); // 4, 3, 2, 1, 0
}

// Array traversal
const fruits = ["apple", "banana", "cherry"];
for (let i = 0; i < fruits.length; i++) {
console.log(`${i}: ${fruits[i]}`);
}

// Nested for: 2D array
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
for (let row = 0; row < matrix.length; row++) {
for (let col = 0; col < matrix[row].length; col++) {
process.stdout.write(matrix[row][col] + " ");
}
console.log();
}

while Loop

Repeats while condition is true.

let count = 0;
while (count < 5) {
console.log(count);
count++;
}

// Infinite loop + break
let input = "";
while (true) {
input = getNextInput();
if (input === "quit") break;
processInput(input);
}

do-while Loop

Executes first, then checks condition. Always runs at least once.

let result;
do {
result = prompt("Enter a number (1-10):");
} while (isNaN(result) || result < 1 || result > 10);

for...of: Iterable Traversal

Added in ES6, for...of iterates over arrays, strings, Maps, Sets, and other iterables.

// Array
const numbers = [10, 20, 30, 40, 50];
for (const num of numbers) {
console.log(num);
}

// With index using entries()
for (const [index, value] of numbers.entries()) {
console.log(`[${index}] ${value}`);
}

// String
for (const char of "Hello") {
console.log(char); // H, e, l, l, o
}

// Map
const map = new Map([["name", "Alice"], ["age", 25]]);
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}

// Set
const set = new Set([1, 2, 3, 2, 1]); // deduplication
for (const item of set) {
console.log(item); // 1, 2, 3
}

for...in: Object Property Enumeration

const user = { name: "Alice", age: 25, city: "New York" };

for (const key in user) {
console.log(`${key}: ${user[key]}`);
}

Caution with for...in

// Includes prototype chain properties!
// Use hasOwnProperty to filter

// Better approach: Object.keys or Object.entries
for (const key of Object.keys(user)) {
console.log(key); // Only own properties
}

for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}

forEach vs for...of

const arr = [1, 2, 3, 4, 5];

// forEach: callback style
arr.forEach((item, index) => {
console.log(`${index}: ${item}`);
});
// Limitation: cannot use break, continue, or return (outer)

// for...of: iteration protocol
for (const item of arr) {
if (item === 3) break; // OK!
console.log(item);
}

// Async processing: for...of supports await
async function processItems(items) {
for (const item of items) {
await processItem(item); // Sequential processing
}
}

// forEach doesn't work properly with async/await
async function badAsync(items) {
items.forEach(async (item) => {
await processItem(item); // All start simultaneously!
});
// forEach doesn't wait for Promises
}

break and continue

// break: immediately exits loop
const numbers = [1, 5, 3, 8, 2, 9, 4];
let target = -1;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] > 7) {
target = numbers[i];
break;
}
}
console.log(target); // 8

// continue: skip current iteration
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) continue; // skip evens
console.log(i); // 1, 3, 5, 7, 9
}

// Labels: control outer loop in nested loops
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // exit outer loop
}
console.log(`${i},${j}`);
}
}

Pro Tips

Loop Selection Guide

// Iterate array elements → for...of or forEach
for (const item of array) { }
array.forEach(item => { });

// Transform array → map
const doubled = array.map(x => x * 2);

// Filter array → filter
const evens = array.filter(x => x % 2 === 0);

// Object properties → for...of + Object.entries
for (const [key, value] of Object.entries(obj)) { }

// Async sequential processing → for...of + await
for (const item of items) {
await process(item);
}

// Async parallel processing → Promise.all + map
await Promise.all(items.map(item => process(item)));
Advertisement