AWESOME CODING

# Step 6: Loops

April 30, 2021 One of the things that computer programs really excel at is repetition. We can easily write a program that would make a computer perform a given operation hundreds or billions of times with a change of a single number. This is one of the things that makes programming so powerful. Once we have an operation that successfully works on one value, it is fairly easy to scale that operation to work on thousands or even millions of values. A loop is a programming structure that allows us to perform these kinds of repeating, iterative operations. There are a bunch of ways to write loops. Newer ways of creating loops have been introduced to JavaScript with the language's development over the years. One of the most foundational ways of creating a loop is by using a `while` loop.

## while Loop

A `while` loop is a loop that works indefinitely as long as the condition that enables the loop is satisfied. Here is an example of a `while` loop. Beware that this is an infinite loop. It would run continuously until we somehow terminate the program.

``````let x = 0;

while (x < 10) {
console.log("This is an infinite loop.");
}
``````

We start with the keyword `while`. We then write a condition next to the `while` keyword inside the parenthesis. This loop will run while this condition is `true`. We then write the logic that we want to execute inside the loop by using curly brackets. In this example, `x` is always going to be smaller than `10`. This means that the loop will always run. This is an infinite loop.

Infinite loops have their uses, but we usually want to have loops that execute a limited amount of times. We can achieve this using a `while` loop as well. We just need to ensure that the condition that makes the loop run evaluates to `false` after a while.

Here is an example of a `while` loop that runs 10 times.

``````let x = 0;

while (x < 10) {
console.log(x);
x = x + 1;
}
``````

What is different with this loop is that the value of `x` does not stay the same. We increase the value of `x` by `1` every time this loop runs. `x = x + 1` means, take the current value of `x`, add `1` to it and assign the new value to be the current value of `x`.

Note that we are using the `let` keyword when declaring the variable `x` since if we were to use `const`, we wouldn't be able to assign a new value to `x`.

## Example: Writing a Countdown Function Using a While Loop

Let's create a function that would countdown from 10 to 1. At the end of the countdown, it should display a given text value.

``````countdown("Launch!");
// Counts down from 10 to 1. Then displays "Launch!" to the screen.
// 10
// 9
// ...
// Launch!
``````

Let's also make it so that the countdown value would be adjustable. If there is no second argument provided, it should countdown from 10. But a second argument can be passed to customize this value to be anything we want (as long as the given value is above 1).

``````countdown("Launch!", 3);
// Counts down from 3 to 1. Then displays "Launch!" to the screen.
// 3
// 2
// 1
// Launch!
``````

We should start by writing the skeleton for our function.

``````function countdown(message, startingNumber = 10) {}

countdown("Launch!");
``````

We will create a `while` loop inside the `countdown` function and make it start from the `startingNumber`. The loop should continue while the `startingNumber` is bigger than `0`.

``````function countdown(message, startingNumber = 10) {
while (startingNumber > 0) {
console.log(startingNumber);
startingNumber = startingNumber - 1;
}
}

countdown("Launch!");
``````

With each iteration of the loop, we are subtracting `1` from the `startingNumber`. When the `startingNumber` reaches `0`, the loop will stop working.

The final thing that we need to do here is to make use of the `message` variable. And let's test it by passing a different `startingNumber`.

``````function countdown(message, startingNumber = 10) {
while (startingNumber > 0) {
console.log(startingNumber);
startingNumber = startingNumber - 1;
}

console.log(message);
}

countdown("Launch!", 15);
``````

We also need to ensure that the user is passing a starting number that is above `1`.

``````function countdown(message, startingNumber = 10) {
if (startingNumber <= 1) {
console.log("Please enter a number bigger than 1.");
return;
}

while (startingNumber > 0) {
console.log(startingNumber);
startingNumber = startingNumber - 1;
}

console.log(message);
}

countdown("Launch!", 0);
``````

Here we have added a check to see if the `startingNumber` is above 1. If it is not we are displaying an error message and returning from the function.

## for Loop

Since it is very common to write loops that only execute for a given amount of time, JavaScript has a dedicated structure for it. It is called a `for` loop. Here is how to build a `for` loop.

``````for (let counter = 0; counter < 10; counter = counter + 1) {
console.log("This for a for loop");
}
``````

A `for` loop has five parts:

• The `for` keyword.
• There is a parenthesis next to the `for` keyword. Inside there, the first section is for the initialization of a loop variable. We named this variable to be `counter` in this example, but it can be anything we want.
• The second section of the parenthesis is the loop condition. The loop will run as long as this condition is `true`.
• The third section of the parenthesis is the loop variable incrementation. Here we adjust the loop variable's value so that the loop condition can be satisfied at some point (assuming we are not trying to write an infinite loop).
• The last part of a `for` loop is the body statement. This is what gets executed as part of the loop.

## Example: Writing a Countdown Function Using a for Loop

Let's rewrite our previous example using a `for` loop.

``````function countdown(message, startingNumber = 10) {
if (startingNumber <= 1) {
console.log("Please enter a number bigger than 1.");
return;
}

for (
let countdownNumber = startingNumber;
countdownNumber > 0;
countdownNumber = countdownNumber - 1
) {
console.log(countdownNumber);
}

console.log(message);
}

countdown("Launch!", 5);
``````

`for` loop collects every expression needed for managing a loop in one place (inside the parenthesis next to the `for` keyword). This makes it a bit easier to write and manage a `for` loop. When writing a `while` loop, there is a risk of forgetting to increment the loop variable and create an unintentional infinite loop. The structure of the `for` loop minimizes that risk.

It is worth mentioning that the variable name chosen for `for` loops are usually much shorter for legibility. Conventionally, the letter `i` is used as a loop variable name. We can update our example to reflect that convention.

``````function countdown(message, startingNumber = 10) {
if (startingNumber <= 1) {
console.log("Please enter a number bigger than 1.");
return;
}

for (let i = startingNumber; i > 0; i = i - 1) {
console.log(i);
}

console.log(message);
}

countdown("Launch!", 5);
``````

## Looping Over Collections

As we have learned earlier arrays and strings are collection-like data types. We can loop over these collections using a `while` loop or a `for` loop.

Let's write a function that would display every item of a given array on a separate line.

``````function displayItems(collection) {
for (let i = 0; i < collection.length; i = i + 1) {
console.log(collection[i]);
}
}

const myFavoriteFood = ["pizza", "sushi", "tacos"];
displayItems(myFavoriteFood);
``````

We wrote a `for` loop here that starts a loop from number `0` up until the given collection's length, which is equal to `3` in this case. This means that the loop variable will be assigned the values `0`, `1`, and `2` throughout this loop's execution. We can use these values as indices of items of the given collection.

There are built-in array methods that allow us to iterate over a given array since it is such a common operation to perform.

Two of those methods are `forEach` and `map`.

## forEach Method

The array's `forEach` method executes a given callback function for every item in the array.

``````const myFavoriteFood = ["pizza", "sushi", "tacos"];

myFavoriteFood.forEach(function (item, index, arr) {
console.log(item);
console.log(index);
console.log(arr);
});
``````

The `forEach` method takes a callback function and provides it with three arguments.

• The first argument is the current item in the iteration.
• The second argument is the index of the current item.
• The third item is the array that we are iterating over.

Using `forEach` displaying every item in a given array becomes extremely easy.

``````const myFavoriteFood = ["pizza", "sushi", "tacos"];

myFavoriteFood.forEach(function (item) {
console.log(item);
});
``````

It is common to use the shorthand function definition syntax (arrow function) when defining inline functions. It reduces the amount of code that we need to write. Let's refactor our example to use an arrow function.

``````const myFavoriteFood = ["pizza", "sushi", "tacos"];

myFavoriteFood.forEach((item) => {
console.log(item);
});
``````

## Example: Multiplier Function

Let's write a function called multiplier that gets an array of numbers. It should multiply every item in the array with a given value (or with `2` if a value is not provided). Then it should return a new array with the updated values. It should look like this:

``````const arr = [1, 2, 3, 4, 5];
const newArr = multiplier(arr, 3);

console.log(arr); // [1, 2, 3, 4, 5];
console.log(newArr); // [3, 6, 9, 12, 15];
``````

We are displaying the value of both the given array (`arr`) and the `newArr` to ensure that our function does not change, mutate, the original array. As a general rule, functions should not mutate the given values but return a new value whenever possible.

Let's see how to tackle this example both with a `for` loop and using the `forEach` method.

This is how we would implement this function using a `for` loop.

``````function multiplier(arr, multiplierNum = 2) {
const result = [];

for (let i = 0; i < arr.length; i = i + 1) {
const currentItem = arr[i];
const newItem = currentItem * multiplierNum;
result.push(newItem);
}

return result;
}

const arr = [1, 2, 3, 4, 5];
const newArr = multiplier(arr, 3);

console.log(arr); // [1, 2, 3, 4, 5];
console.log(newArr); // [3, 6, 9, 12, 15];
``````

We are creating an empty array called `result` inside the function body to store the results of our multiplication operation. Then we are creating a `for` loop to iterate over the items of an array. We multiply each item with the given `multiplierNum` value and then `push` this new value into the `result` array. We return the `result` array after the loop is complete.

Same functionality implemented with `forEach` method would look like this.

``````function multiplier(arr, multiplierNum = 2) {
const result = [];

arr.forEach((item) => {
const newItem = item * multiplierNum;
result.push(newItem);
});

return result;
}

const arr = [1, 2, 3, 4, 5];
const newArr = multiplier(arr, 3);

console.log(arr); // [1, 2, 3, 4, 5];
console.log(newArr); // [3, 6, 9, 12, 15];
``````

It is a very common operation to iterate over arrays and alter the items' values to create a new array. Arrays have a method called `map` that makes these kinds of operations much easier.

## map Method

A `map` method is similar to a `forEach` method. We pass a callback function to a `map` method that gets executed on every item.

``````const myFavoriteFood = ["pizza", "sushi", "tacos"];

myFavoriteFood.map((item) => {
console.log(item);
});
``````

As we can see, it looks very similar to the `forEach` method. The arguments that the callback function takes are also the same as the `forEach` method. The difference is that the `map` method results in a new array with the items we return from the callback function.

``````const myFavoriteFood = ["pizza", "sushi", "tacos"];

const myNewFavoriteFood = myFavoriteFood.map((item) => {
return "ice cream";
});

console.log(myFavoriteFood); // ["pizza", "sushi", "tacos"];
console.log(myNewFavoriteFood); // ["ice cream", "ice cream", "ice cream"];
``````

Using the `map` method, we are able to construct a new array consisting of whatever we `return` from the callback function.

Writing a `multiplier` function is so much easier when using the `map` method.

``````function multiplier(arr, multiplierNum = 2) {
return arr.map((item) => {
return item * multiplierNum;
});
}

const arr = [1, 2, 3, 4, 5];
const newArr = multiplier(arr, 3);

console.log(arr); // [1, 2, 3, 4, 5];
console.log(newArr); // [3, 6, 9, 12, 15];
``````

Probably, we wouldn't even write a separate `multiplier` function since the `map` method makes it so easy to this operation on the array.

``````const arr = [1, 2, 3, 4, 5];
const newArr = arr.map((item) => item * 3);

console.log(arr); // [1, 2, 3, 4, 5];
console.log(newArr); // [3, 6, 9, 12, 15];
``````

## filter Method

It is a common requirement to go through the items of an array to see if they satisfy a certain condition. For example, imagine having to write a function that would iterate over an array and return all those items that are longer than 4 characters.

``````function checkLength(arr) {}

const arr = ["pizza", "taco", "egg", "sushi", "ice cream"];
const newArr = checkLength(arr);
console.log(newArr); // ["pizza", "sushi", "ice cream"];
``````

We would need to use a `loop` or the `forEach` method to implement this function with our knowledge. `map` wouldn't be applicable here since `map` returns something for each item in an array. Here we don't want to return anything if the item is shorter or equal to 4 characters in length.

``````function checkLength(arr) {
const result = arr.map((item) => {
if (item.length > 4) {
return item;
}
});

return result;
}

const arr = ["pizza", "taco", "egg", "sushi", "ice cream"];
const newArr = checkLength(arr);
console.log(newArr); // ["pizza", undefined, undefined, "sushi", "ice cream"]
``````

Here is what the implementation would look like using a `forEach` method.

``````function checkLength(arr) {
const result = [];

arr.forEach((item) => {
if (item.length > 4) {
result.push(item);
}
});

return result;
}

const arr = ["pizza", "taco", "egg", "sushi", "ice cream"];
const newArr = checkLength(arr);
console.log(newArr); // ["pizza", "sushi", "ice cream"]
``````

This function achieves what we are trying to do, but there is a better way of doing this. It is by using the `filter` method.

``````function checkLength(arr) {
return arr.filter((item) => {
if (item.length > 4) {
return true;
}

return false;
});
}

const arr = ["pizza", "taco", "egg", "sushi", "ice cream"];
const newArr = checkLength(arr);
console.log(newArr); // ["pizza", "sushi", "ice cream"]
``````

The `filter` method takes a callback function that gets provided with the same arguments as `forEach` or the `map` method. The `filter` method iterates over every item and returns a new array that consists of items where the callback function for the item returns `true`. The item will not be included in the final array if the callback function is to return a `false` or a falsy value (like `undefined`).

## Summary

In this chapter, we have learned about loops. A loop is a programming structure that allows us to perform repetitive operations easily. There are a bunch of ways to write loops. We have learned about the `while` and `for` loops. We can use these structures to loop over arrays or write loops that work indefinitely (infinite loops).

When working with collections like arrays or strings, we frequently need to perform operations on every item of that collection.

• Given an array of names, we might want to find a person with a specific name.
• Given an array of numbers, we might want to operate on every number (maybe calculate the square root of all of them.), etc.

This operation of going through every item in a collection is called iteration. We can use `while` or `for` loops to iterate over arrays, but some array methods are better suited to this task. These are `forEach` and `map` methods.

A `forEach` method allows us to iterate over each item of an array and execute a callback function on those items. The `map` method is structurally similar to the `forEach` method, but it returns a new array consisting of the values returned from the callback function.

We have also learned about the `filter` method that is also structurally similar to `forEach` and `map` methods. The `filter` is similar to the `map` method in that it also returns a new array. We can use the `filter` method to eliminate the items in an array that we don't need.