Loops allow you to execute code repeatedly, making it possible to work with collections of data and perform repetitive tasks efficiently. Understanding loops is fundamental for processing arrays, handling user input, and creating dynamic applications.
Loops are programming constructs that allow you to execute a block of code repeatedly. They are essential for tasks that require repetitive operations, such as processing collections of data, generating sequences, or performing calculations multiple times.
Without loops, you would need to write the same code multiple times to perform repetitive tasks. This approach is inefficient, error-prone, and difficult to maintain. Loops provide a clean, scalable solution for repetition.
JavaScript provides several types of loops, each designed for specific scenarios:
The for loop is the most common type of loop in JavaScript. It's perfect when you know exactly how many times you want to execute a block of code.
for (initialization; condition; final-expression) {
// code to be executed
}
// Count from 1 to 5
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// Count backwards
for (let i = 10; i >= 0; i--) {
console.log(i);
}
// Increment by 2
for (let i = 0; i <= 10; i += 2) {
console.log(i);
}
const fruits = ['apple', 'banana', 'orange'];
for (let i = 0; i < fruits.length; i++) {
console.log(`Fruit ${i + 1}: ${fruits[i]}`);
}
// Sum of numbers
let sum = 0;
for (let i = 1; i <= 10; i++) {
sum += i;
}
console.log(sum); // 55
// Finding maximum value
const numbers = [3, 7, 2, 9, 4];
let max = numbers[0];
for (let i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
console.log(max); // 9
The while loop continues executing as long as the specified condition evaluates to true. It's useful when you don't know in advance how many iterations you need.
while (condition) {
// code to be executed
}
// Count while condition is true
let count = 1;
while (count <= 5) {
console.log(count);
count++;
}
// Continue until user input is valid
let userInput = '';
while (userInput !== 'quit') {
userInput = prompt('Enter a command (or "quit" to exit):');
console.log('You entered:', userInput);
}
Be careful with while loops - if the condition never becomes false, you'll create an infinite loop:
// DANGEROUS - Infinite loop!
// let x = 0;
// while (x < 10) {
// console.log(x);
// // Forgot to increment x!
// }
// Generate random numbers until we get one greater than 0.9
let randomNum;
let attempts = 0;
do {
randomNum = Math.random();
attempts++;
console.log(`Attempt ${attempts}: ${randomNum}`);
} while (randomNum <= 0.9);
console.log(`Got ${randomNum} after ${attempts} attempts`);
The do-while loop is similar to the while loop, but it guarantees that the loop body will execute at least once, even if the condition is initially false.
do {
// code to be executed
} while (condition);
// while loop - might not execute at all
let x = 10;
while (x < 5) {
console.log('This will never print');
}
// do-while loop - always executes at least once
do {
console.log('This will print once');
} while (x < 5);
// Menu-driven program
let choice;
do {
console.log('1. Add item');
console.log('2. View items');
console.log('3. Exit');
choice = prompt('Enter your choice:');
} while (choice !== '3');
// Input validation
let number;
do {
number = parseInt(prompt('Enter a positive number:'));
} while (isNaN(number) || number <= 0);
console.log('Valid number entered:', number);
JavaScript provides statements to control the flow of loops: break and continue.
The break statement immediately terminates the loop and continues execution at the statement following the loop.
// Find first number greater than 50
const numbers = [10, 25, 30, 60, 45, 80];
let found = null;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] > 50) {
found = numbers[i];
break; // Exit the loop
}
}
console.log('First number > 50:', found); // 60
The continue statement skips the current iteration and continues with the next iteration.
// Print only odd numbers
for (let i = 1; i <= 10; i++) {
if (i % 2 === 0) {
continue; // Skip even numbers
}
console.log(i); // 1, 3, 5, 7, 9
}
// Skip invalid data
const data = [10, null, 20, undefined, 30, 0, 40];
let sum = 0;
for (let i = 0; i < data.length; i++) {
if (data[i] == null || data[i] === 0) {
continue; // Skip null, undefined, and zero
}
sum += data[i];
}
console.log('Sum:', sum); // 100
You can use labels to break or continue from nested loops:
outer: for (let i = 1; i <= 3; i++) {
for (let j = 1; j <= 3; j++) {
if (i === 2 && j === 2) {
break outer; // Exit both loops
}
console.log(`${i},${j}`);
}
}
// Output: 1,1 1,2 1,3 2,1
The for...in loop iterates over the enumerable properties of an object. It's primarily used for objects, not arrays.
for (key in object) {
// code to be executed
}
const person = {
name: 'John',
age: 30,
city: 'New York'
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// Output:
// name: John
// age: 30
// city: New York
const colors = ['red', 'green', 'blue'];
for (let index in colors) {
console.log(`${index}: ${colors[index]}`);
}
// Works, but not recommended for arrays
for...in iterates over property names (strings), not valuesfor...of or array methods insteadThe for...of loop creates a loop iterating over iterable objects (including Array, Map, Set, String, etc.).
for (variable of iterable) {
// code to be executed
}
const fruits = ['apple', 'banana', 'orange'];
for (let fruit of fruits) {
console.log(fruit);
}
// Output: apple, banana, orange
const message = 'Hello';
for (let char of message) {
console.log(char);
}
// Output: H, e, l, l, o
// Set
const uniqueNumbers = new Set([1, 2, 3, 3, 4]);
for (let num of uniqueNumbers) {
console.log(num); // 1, 2, 3, 4
}
// Map
const contacts = new Map([
['John', '555-1234'],
['Jane', '555-5678']
]);
for (let [name, phone] of contacts) {
console.log(`${name}: ${phone}`);
}
Modern JavaScript provides powerful array methods that often replace traditional loops for common operations.
Executes a function for each array element.
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num, index) => {
console.log(`Index ${index}: ${num}`);
});
// Using forEach to modify array elements
const doubled = [];
numbers.forEach(num => {
doubled.push(num * 2);
});
console.log(doubled); // [2, 4, 6, 8, 10]
Creates a new array by applying a function to each element.
const numbers = [1, 2, 3, 4, 5];
const squared = numbers.map(num => num * num);
console.log(squared); // [1, 4, 9, 16, 25]
// Transform objects
const users = [
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 }
];
const names = users.map(user => user.name);
console.log(names); // ['John', 'Jane']
Creates a new array with elements that pass a test.
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6, 8, 10]
// Filter objects
const products = [
{ name: 'Laptop', price: 1000 },
{ name: 'Phone', price: 500 },
{ name: 'Tablet', price: 300 }
];
const expensiveProducts = products.filter(product => product.price > 400);
console.log(expensiveProducts);
// [{ name: 'Laptop', price: 1000 }, { name: 'Phone', price: 500 }]
Reduces an array to a single value by applying a function.
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 15
// Find maximum
const max = numbers.reduce((max, current) =>
current > max ? current : max, numbers[0]);
console.log(max); // 5
// Group objects
const people = [
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 },
{ name: 'Bob', age: 30 }
];
const groupedByAge = people.reduce((groups, person) => {
const age = person.age;
if (!groups[age]) {
groups[age] = [];
}
groups[age].push(person.name);
return groups;
}, {});
console.log(groupedByAge);
// { '25': ['Jane'], '30': ['John', 'Bob'] }
Find the first element that satisfies a condition.
const numbers = [1, 2, 3, 4, 5];
const found = numbers.find(num => num > 3);
console.log(found); // 4
const foundIndex = numbers.findIndex(num => num > 3);
console.log(foundIndex); // 3
// With objects
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 3, name: 'Bob' }
];
const user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: 'Jane' }
Test whether some or all elements pass a condition.
const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // true
const allGreaterThanTen = numbers.every(num => num > 10);
console.log(allGreaterThanTen); // false
Nested loops are loops inside other loops. They're useful for working with multi-dimensional data structures.
// Multiplication table
for (let i = 1; i <= 5; i++) {
for (let j = 1; j <= 5; j++) {
console.log(`${i} × ${j} = ${i * j}`);
}
}
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// Print all elements
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
console.log(matrix[i][j]);
}
}
// Find a specific value
let target = 5;
let found = false;
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] === target) {
console.log(`Found ${target} at position [${i}][${j}]`);
found = true;
break;
}
}
if (found) break;
}
Nested loops can be expensive computationally:
// This can be slow for large arrays!
const array1 = [1, 2, 3, 4, 5];
const array2 = [10, 20, 30, 40, 50];
for (let i = 0; i < array1.length; i++) {
for (let j = 0; j < array2.length; j++) {
console.log(array1[i] + array2[j]);
}
}
for loop when you need the index and know the iteration countwhile loop when the condition depends on runtime factorsfor...of loop for iterating over array valuesmap, filter, reduce) for functional programmingfor...in for arrays - it's meant for objects// Cache array length
const arr = [1, 2, 3, 4, 5];
for (let i = 0, len = arr.length; i < len; i++) {
console.log(arr[i]);
}
// Use reverse loop when possible (slightly faster)
for (let i = arr.length - 1; i >= 0; i--) {
console.log(arr[i]);
}
// Prefer array methods over manual loops
const numbers = [1, 2, 3, 4, 5];
// Good
const doubled = numbers.map(n => n * 2);
// Less efficient
const doubled2 = [];
for (let i = 0; i < numbers.length; i++) {
doubled2.push(numbers[i] * 2);
}
// Don't modify array while iterating
const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 3) {
arr.splice(i, 1); // This can cause issues!
i--; // Decrement to compensate
}
}
// Better approach: filter
const filtered = arr.filter(item => item !== 3);
// Be careful with large datasets
const largeArray = new Array(1000000).fill(0);
// This creates a new array - memory intensive
const doubled = largeArray.map(x => x * 2);
// This processes one item at a time - more memory efficient
for (let i = 0; i < largeArray.length; i++) {
processItem(largeArray[i] * 2);
}
const salesData = [
{ product: 'Laptop', quantity: 5, price: 1000 },
{ product: 'Mouse', quantity: 10, price: 25 },
{ product: 'Keyboard', quantity: 8, price: 75 }
];
// Calculate total revenue
let totalRevenue = 0;
for (const sale of salesData) {
totalRevenue += sale.quantity * sale.price;
}
console.log('Total Revenue:', totalRevenue);
// Using reduce
const revenue = salesData.reduce((total, sale) =>
total + (sale.quantity * sale.price), 0);
console.log('Revenue (reduce):', revenue);
const users = [
{ name: 'John', age: 30, city: 'New York' },
{ name: 'Jane', age: 25, city: 'Boston' },
{ name: 'Bob', age: 35, city: 'New York' },
{ name: 'Alice', age: 28, city: 'Chicago' }
];
// Find users from New York
const nyUsers = users.filter(user => user.city === 'New York');
console.log('NY Users:', nyUsers);
// Find user by name
const findUser = (name) => {
for (const user of users) {
if (user.name.toLowerCase() === name.toLowerCase()) {
return user;
}
}
return null;
};
console.log('Find Jane:', findUser('Jane'));
const rawData = [
' apple ',
'banana',
' ORANGE ',
'grape'
];
// Clean and capitalize fruit names
const cleanedFruits = rawData
.map(fruit => fruit.trim().toLowerCase())
.filter(fruit => fruit.length > 0)
.map(fruit => fruit.charAt(0).toUpperCase() + fruit.slice(1));
console.log(cleanedFruits); // ['Apple', 'Banana', 'Orange', 'Grape']
Loops are fundamental programming constructs that enable repetitive code execution. JavaScript provides various loop types and iteration methods, each suited for different scenarios:
map, filter, reduce) often provide cleaner, more readable codebreak and continue to control loop flow when neededfor...of over for...in for array iterationfor loops for better performancefor loop: Known iteration count, need index accesswhile loop: Unknown iteration count, condition-baseddo-while loop: Need at least one executionfor...of loop: Iterating over iterable valuesfor...in loop: Iterating over object propertiesMastering loops and iteration is essential for writing efficient, clean JavaScript code. Practice with different scenarios to understand when each approach is most appropriate.