JavaScript Loops: Detailed Guide from Beginner to Complex

Understand JavaScript loops with Edulane. This guide covers beginner to complex topics, including for, while, and do-while loops with practical examples.

Overview

This guide covers JavaScript loops, arrays, and complex examples. It starts with basic loops, moves to intermediate and complex loops, and provides advanced examples that demonstrate practical applications in Data Structures and Algorithms (DSA).

Basic Loops

for Loop

The for loop is used for iterating a known number of times.

Syntax:
for (initialization; condition; increment) {
  // code to be executed
}
Example:
for (let i = 0; i < 5; i++) {
  console.log(i);
}
  1. Explanation:
    • Initialization: let i = 0 initializes the loop counter.
    • Condition: i < 5 is evaluated before each iteration. If true, the loop body executes.
    • Increment: i++ increases the counter after each iteration.
  2. Best Practices:
    • Use descriptive variable names.
    • Ensure termination to avoid infinite loops.

while Loop

The while loop runs as long as the condition remains true.

Syntax:
while (condition) {
  // code to be executed
}
Example:
let i = 0;
while (i < 5) {
  console.log(i);
  i++;
}
  1. Explanation:
    • Condition:i < 5 is checked before each iteration.
    • Loop Body: Executes as long as the condition is true.
    • Increment:i++ updates the loop counter within the loop body.
  2. Best Practices:
    • Ensure the condition will eventually become false

do…while Loop

The do...while loop ensures the loop body executes at least once.

Syntax:
do {
  // code to be executed
} while (condition);
Example:
let i = 0;
do {
  console.log(i);
  i++;
} while (i < 5);
  1. Explanation:
    • Loop Body: Executes first.
    • Condition: i < 5 is checked after each iteration.
  2. Best Practices:
    • Use when at least one execution is required.

Intermediate Loops

for…in Loop

The for...in loop iterates over enumerable properties of an object.

Syntax:
for (key in object) {
  // code to be executed
}
Example:
const person = {
  name: 'Alice',
  age: 30,
  city: 'Wonderland'
};

for (let key in person) {
  console.log(key + ': ' + person[key]);
}
  1. Explanation:
    • Key: Represents each property name in the object.
    • person[key]: Accesses the property value.
  2. Best Practices:
    • Use for object properties, not arrays.
    • Filter inherited properties with hasOwnProperty.

for…of Loop

The for...of loop is used to iterate over iterable objects like arrays and strings.

Syntax:
for (let value of iterable) {
  // code to be executed
}
Example:
const numbers = [1, 2, 3, 4, 5];

for (let number of numbers) {
  console.log(number);
}
  1. Explanation:
    • Value: Represents each element in the iterable.
  2. Best Practices:
    • Use for arrays and other iterables.
    • Provides cleaner syntax than traditional loops.

Complex Loops

Nested Loops

Nested loops involve one loop inside another and are useful for multi-dimensional structures.

Syntax:
for (let i = 0; i < outerLimit; i++) {
  for (let j = 0; j < innerLimit; j++) {
    // code to be executed
  }
}
Example:
for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    console.log(`i: ${i}, j: ${j}`);
  }
}
  1. Explanation:
    • Outer Loop: Iterates over i.
    • Inner Loop: Iterates over j for each i.
  2. Best Practices:
    • Be cautious with performance; ensure efficient logic.

Arrays

Arrays are used to store multiple values in a single variable. They are indexed collections of items that can be of any type, including numbers, strings, or objects.

// Arrays are used to store multiple values in a single variable.
// They are indexed collections, which means each element is accessed via an index.

const numbers = [1, 2, 3, 4, 5]; // An array of numbers

console.log("Initial array:", numbers);

// Accessing Elements
console.log("First element:", numbers[0]); // Output: 1
console.log("Second element:", numbers[1]); // Output: 2

// Adding Elements
// Push adds an element to the end of the array
numbers.push(6);
console.log("After push:", numbers); // Output: [1, 2, 3, 4, 5, 6]

// Unshift adds an element to the beginning of the array
numbers.unshift(0);
console.log("After unshift:", numbers); // Output: [0, 1, 2, 3, 4, 5, 6]

// Removing Elements
// Pop removes the last element of the array
numbers.pop();
console.log("After pop:", numbers); // Output: [0, 1, 2, 3, 4, 5]

// Shift removes the first element of the array
numbers.shift();
console.log("After shift:", numbers); // Output: [1, 2, 3, 4, 5]

// Iterating Over Arrays
// Using a for loop
for (let i = 0; i < numbers.length; i++) {
  console.log("Element at index", i, ":", numbers[i]);
}

// Using for...of loop
for (let num of numbers) {
  console.log("Value:", num);
}

// Using forEach() method
numbers.forEach((num, index) => {
  console.log("Element at index", index, ":", num);
});

// Common Array Methods
// slice creates a shallow copy of a portion of an array
const slicedArray = numbers.slice(1, 4);
console.log("Sliced array:", slicedArray); // Output: [2, 3, 4]

// splice changes the contents of an array by removing or replacing elements
numbers.splice(2, 1, 10); // Removes 1 element at index 2 and adds 10
console.log("After splice:", numbers); // Output: [1, 2, 10, 4, 5]

// concat merges two or more arrays
const moreNumbers = [7, 8, 9];
const combinedArray = numbers.concat(moreNumbers);
console.log("Combined array:", combinedArray); // Output: [1, 2, 10, 4, 5, 7, 8, 9]

// map creates a new array with the results of calling a provided function on every element
const doubledNumbers = numbers.map(num => num * 2);
console.log("Doubled numbers:", doubledNumbers); // Output: [2, 4, 20, 8, 10]

// filter creates a new array with all elements that pass the test implemented by the provided function
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log("Even numbers:", evenNumbers); // Output: [2, 10, 4]

// reduce applies a function against an accumulator and each element to reduce it to a single value
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log("Sum of numbers:", sum); // Output: 22

// find returns the first element that satisfies the provided testing function
const firstGreaterThanFive = numbers.find(num => num > 5);
console.log("First number greater than 5:", firstGreaterThanFive); // Output: 10

// sort sorts the elements of an array in place
const sortedNumbers = numbers.slice().sort((a, b) => a - b); // Sorts in ascending order
console.log("Sorted numbers:", sortedNumbers); // Output: [1, 2, 4, 5, 10]

// reverse reverses the elements of an array in place
const reversedNumbers = numbers.slice().reverse();
console.log("Reversed numbers:", reversedNumbers); // Output: [5, 4, 10, 2, 1]

// length property gives the number of elements in the array
console.log("Length of array:", numbers.length); // Output: 5

// Checking if a value is in the array
const containsThree = numbers.includes(3);
console.log("Array contains 3:", containsThree); // Output: true

const indexOfThree = numbers.indexOf(3);
console.log("Index of 3:", indexOfThree); // Output: 2

// Joining array elements into a string
const joinedString = numbers.join(", ");
console.log("Joined string:", joinedString); // Output: "1, 2, 10, 4, 5"

Basic Operations

  • Accessing Elements: Use indices to access specific elements in an array.
  • Adding Elements:
    • push(): Adds to the end.
    • unshift(): Adds to the beginning.
  • Removing Elements:
    • pop(): Removes from the end.
    • shift(): Removes from the beginning.

Iterating Over Arrays

  • for Loop: Basic iteration using index.
  • for...of Loop: Simplified iteration over values.
  • forEach() Method: Executes a provided function once for each array element.

Common Array Methods

  • slice(): Creates a shallow copy of a portion of the array.
  • splice(): Modifies the array by adding/removing elements.
  • concat(): Merges arrays.
  • map(): Creates a new array with modified values.
  • filter(): Creates a new array with elements that pass a test.
  • reduce(): Reduces the array to a single value.
  • find(): Returns the first element that satisfies the condition.
  • sort(): Sorts elements.
  • reverse(): Reverses the array.
  • length: Returns the number of elements.
  • includes(): Checks if an element exists.
  • indexOf(): Returns the index of an element.
  • join(): Joins elements into a string.

Please check Array and Array Iteration Lessons where we have explained in detail.

Advanced Examples

Example 1: Matrix Multiplication

Problem: Multiply two matrices –

function multiplyMatrices(A, B) {
  const rowsA = A.length;
  const colsA = A[0].length;
  const colsB = B[0].length;
  
  let result = Array.from({ length: rowsA }, () => Array(colsB).fill(0));
  
  for (let i = 0; i < rowsA; i++) {
    for (let j = 0; j < colsB; j++) {
      for (let k = 0; k < colsA; k++) {
        result[i][j] += A[i][k] * B[k][j];
      }
    }
  }
  return result;
}

const A = [
  [1, 2, 3],
  [4, 5, 6]
];

const B = [
  [7, 8],
  [9, 10],
  [11, 12]
];

console.log(multiplyMatrices(A, B));

// Output [ [ 58, 64 ], [ 139, 154 ] ]
Explanation:
  • Outer Loop: Iterates over rows of A.
  • Middle Loop: Iterates over columns of B.
  • Inner Loop: Calculates the dot product for each cell.

Example 2: Spiral Order Matrix Traversal

Problem: Print matrix elements in spiral order-
function spiralOrder(matrix) {
  const result = [];
  const rows = matrix.length;
  const cols = matrix[0].length;
  let top = 0, bottom = rows - 1;
  let left = 0, right = cols - 1;

  while (top <= bottom && left <= right) {
    for (let i = left; i <= right; i++) result.push(matrix[top][i]);
    top++;
    for (let i = top; i <= bottom; i++) result.push(matrix[i][right]);
    right--;
    if (top <= bottom) {
      for (let i = right; i >= left; i--) result.push(matrix[bottom][i]);
      bottom--;
    }
    if (left <= right) {
      for (let i = bottom; i >= top; i--) result.push(matrix[i][left]);
      left++;
    }
  }
  return result;
}

const matrix = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12]
];

console.log(spiralOrder(matrix));
/*
Output 
[
   1,  2,  3, 4, 8,
  12, 11, 10, 9, 5,
   6,  7
]
*/
Explanation:
  • Four Boundaries: Top, bottom, left, and right are adjusted to traverse the matrix in spiral order.
  • Direction: Traverse right, down, left, and up, updating boundaries after each traversal.

Example 3: Generating Pascal’s Triangle

Problem: Generate the first n rows of Pascal’s Triangle-
function generatePascalTriangle(n) {
  const result = [];
  
  for (let i = 0; i < n; i++) {
    const row = Array(i + 1).fill(1);
    for (let j = 1; j < i; j++) {
      row[j] = result[i - 1][j - 1] + result[i - 1][j];
    }
    result.push(row);
  }
  
  return result;
}

console.log(generatePascalTriangle(5));

// Output - [ [ 1 ], [ 1, 1 ], [ 1, 2, 1 ], [ 1, 3, 3, 1 ], [ 1, 4, 6, 4, 1 ] ]
Explanation:
  • Outer Loop: Iterates over rows.
  • Inner Loop: Calculates values based on the previous row.

Example 4: Finding Prime Numbers (Sieve of Eratosthenes)

Problem: Find all prime numbers up to a given limit-
function sieveOfEratosthenes(limit) {
  const primes = Array(limit + 1).fill(true);
  primes[0] = primes[1] = false;
  
  for (let p = 2; p * p <= limit; p++) {
    if (primes[p]) {
      for (let i = p * p; i <= limit; i += p) {
        primes[i] = false;
      }
    }
  }
  
  return primes.map((isPrime, num) => isPrime ? num : -1).filter(num => num !== -1);
}

console.log(sieveOfEratosthenes(30));

/* 
Output
[
   2,  3,  5,  7, 11,
  13, 17, 19, 23, 29
]
*/
Explanation:
  • Prime Array: Tracks prime status of numbers.
  • Outer Loop: Iterates over possible prime candidates.
  • Inner Loop: Marks multiples of each prime as non-prime.

Example 5: Fibonacci Sequence (Dynamic Programming)

Problem: Compute the Fibonacci sequence using dynamic programming-
function fibonacci(n) {
  if (n <= 1) return n;
  const dp = Array(n + 1).fill(0);
  dp[1] = 1;
  
  for (let i = 2; i <= n; i++) {
    dp[i] = dp[i - 1] + dp[i - 2];
  }
  
  return dp[n];
}

console.log(fibonacci(10));

// Output - 55
Explanation:
  • DP Array: Stores Fibonacci numbers up to n.
  • Loop: Iterates to fill the DP array based on previous values.

Interview Questions:

Here are 20 JavaScript loop interview questions along with their answers.

1. Question: What is the syntax of a for loop in JavaScript?

Answer:

for (initialization; condition; increment) {
    // code block to be executed
}

2. Question: How do you iterate over an array using a for loop?

Answer:

const array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
    console.log(array[i]);
}

3. Question: What is the difference between for...in and for...of loops?

Answer:

  • for...in iterates over the keys of an object.
  • for...of iterates over the values of an iterable object (like arrays or strings).

4. Question: How would you print all the elements of an object using a for...in loop?

Answer:

const obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
    console.log(key + ": " + obj[key]);
}

5. Question: How do you create an infinite loop in JavaScript?

Answer:

while (true) {
    // code block to be executed
}

6. Question: Write a while loop that prints numbers from 1 to 5.

Answer:

let i = 1;
while (i <= 5) {
    console.log(i);
    i++;
}

7. Question: How does a do...while loop differ from a while loop?

Answer:

A do...while loop executes the code block once before checking the condition, ensuring it runs at least once. A while loop checks the condition before executing the code block.

8. Question: Write a do...while loop that prints numbers from 1 to 5.

Answer:

let i = 1;
do {
    console.log(i);
    i++;
} while (i <= 5);

9. Question: How can you loop through an array using for...of?

Answer:

const array = [1, 2, 3, 4, 5];
for (let value of array) {
    console.log(value);
}

10. Question: Write a for loop that prints the multiplication table of 7.

Answer:

for (let i = 1; i <= 10; i++) {
    console.log(`7 x ${i} = ${7 * i}`);
}

11. Question: How can you use a for loop to calculate the factorial of a number?

Answer:

function factorial(n) {
    let result = 1;
    for (let i = n; i > 1; i--) {
        result *= i;
    }
    return result;
}
console.log(factorial(5)); // Output: 120

12. Question: How do you use a for loop to iterate over a string and print each character?

Answer:

const str = "hello";
for (let i = 0; i < str.length; i++) {
    console.log(str[i]);
}

13. Question: Write a for...of loop to iterate over a string and print each character.

Answer:

const str = "hello";
for (let char of str) {
    console.log(char);
}

14. Question: How do you use a for...in loop to count the number of properties in an object?

Answer:

const obj = { a: 1, b: 2, c: 3 };
let count = 0;
for (let key in obj) {
    count++;
}
console.log(count); // Output: 3

15. Question: What are the potential pitfalls of using a for...in loop with arrays?

Answer:

  • for...in iterates over all enumerable properties, including inherited properties.
  • The iteration order is not guaranteed.
  • It is not suitable for arrays; use for or for...of instead.

16. Question: Write a for...of loop to iterate over a Map and print its entries.

Answer:

const map = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let [key, value] of map) {
    console.log(key + ": " + value);
}

17. Question: How can you use a for loop to sum the elements of an array?

Answer:

const array = [1, 2, 3, 4, 5];
let sum = 0;
for (let i = 0; i < array.length; i++) {
    sum += array[i];
}
console.log(sum); // Output: 15

18. Question: Write a while loop to reverse a string.

Answer:

let str = "hello";
let reversed = "";
let i = str.length - 1;
while (i >= 0) {
    reversed += str[i];
    i--;
}
console.log(reversed); // Output: "olleh"

19. Question: Explain how you would use a for loop to print a right-angled triangle of stars.

Answer:

let rows = 5;
for (let i = 1; i <= rows; i++) {
    let stars = '';
    for (let j = 1; j <= i; j++) {
        stars += '*';
    }
    console.log(stars);
}
Output:
*
**
***
****
*****

20. Question: How do you break out of a loop prematurely?

Answer:

Use the break statement:

for (let i = 0; i < 10; i++) {
    if (i === 5) {
        break;
    }
    console.log(i);
}
// Output: 0 1 2 3 4