TLDR; This article teaches you the various loop constructs that exist in JavaScript and which one to use when.
Iteration/Looping
Sometimes we have structures that requires us to loop through them. What we mean is that we want to look through every single item in that construct and do something with it. Here's some areas of application:
Display every item. A very common application is to show every item in a list visually. A common example is to show every item in a cart on an e-commerce site, so you can see what you are about to purchase. There are many loop constructs that help you with displaying everything in a list like
for
,for/in
,for/of
to name a few. You will learn more about how thy differ further down in the article.Map. Mapping is about iterating through a structure and change it from one form to another form. You typically want to do this when the data you have isn't quite ready for its next step. The next step can be to display your data and you want to change from a data object to something more presentable.
Reduce. When you reduce data you go from one form to a reduced form. So what does that mean? It means that instead of a list of order items you reduce them down to something interesting, the total sum of the items for example.
Iterate items
To iterate items there are many construct available to you. Let's start with a simple for-loop
. It is made up in the following way:
for(<start condition>; <break condition>; <incremental phase> ) {
}
The idea is to define a loop as having the following stages:
Start condition. In the start condition you initialize the loop value to a certain value, like for example
let i=0;
.Break condition. Next you define break condition, that when fulfilled, will stop the loop from further iterations, for example
i< 5
.Increment phase. Lastly you define how much you want the loop variable to increase/decrease per iteration.
A typical for-loop
can look like so:
for (let i =0; i < 5; i++) {
}
It's common to name the variable i
, for index, i.e the current position in the loop. It's better to give it a more descriptive name like so:
for (let position =0; position < cart.length; position++) {
}
NOTE, I'm using
let
to ensure we have block scope, so thatposition
seize to exist after the loop is done.var
will NOT give you block scope and leaks outside of the loop.
// DON'T
for (var position =0; position < cart.length; position++) {
}
// position is still alive here
For-in
For-in
is one of the most misunderstood loops. I've heard a lot of conversations where people say use for-of
instead but not why. So let's explain what's going on.
For-in
lists the attributes of the object. Let's show what's meant by the below code:
let object = {
name: 'chris',
city: 'London'
};
for (let prop in object) {
console.log(prop)
}
// name, city
The problem happens when you think you can use it on an array that looks like so:
let array = [1, 2, 3];
for (let prop in array) {
console.log(prop)
}
// '0', '1', '2'
You're not getting the values in the area but rather the indexes. If you are surprised by this, you should know that most things in JavaScript is actually an object. Consider the below code:
typeof [1,2,3] // 'object'
It tells you that you are dealing with an object. That means that your array looks like so under the hood:
{
"0": 1,
"1": 2,
"2": 3
}
There's also a method that acts similarly on the array namely Object.keys()
. The following code produces a similar result to for-in
:
Object.keys([1,2,3]) // ['0', '1', '2']
NOTE,
for-in
andObject.keys()
have similar area of application and operates on the keys/attributes.
Getting the value
If the values is what you want, then you have a few options:
Object.values([1,2,3]) // 1, 2, 3
You can also use the for-of
loop like so:
for(let obj of arr) {
console.log(obj);
}
// 1,2,3
Or, you can use forEach()
, a method on the array like so:
let arr = [1,2,3];
arr.forEach((item, number, array) => console.log(item))
NOTE, you can't use a
break
statement to stop an iteration using aforEach()
. If you might need to break a loop, consider using a normalfor
construct.
Changing the data
So far, you've been looking at ways to just iterate over all the data but you haven't changed it. You can change the data while iterating through it. Depending on how you want to change the data you got two constructs made for it map()
and reduce()
.
Map
map()
is function on the array data structure. The idea is to iterate over all the items in an array and change that item into something new. It could be that you are only interested in certain properties on an object or that you want to change from a data model to something more presentable, a view model.
Lets look at an example:
let heroes = [{
name: 'Xena',
country: 'Greece'
}, {
name: 'Alexander the Great',
country: 'Macedonia'
}]
let onlyTheName = heroes.map(hero => {
return hero.name;
});
// can also be written as: let onlyTheName = heroes.map(hero => hero.name)
onlyTheName.forEach(name => console.log(name)) // ['Xena', 'Alexander the Great']
Above you have an example of iterating through an array and plucking out the the attribute name
that you are interested in.
Reduce
The reduce()
function, just like map()
is on the array data structure. It also seeks to change every item, but there's an important distinction. reduce()
cares about performing an operation on the item and add the result to a previous result in an earlier iteration. This makes reduce()
a good candidate to use if you want to for example get the sum of all cart items or if you want to merge a cet of objects into one. Lets look at both these examples:
let arr = [1,2,3,4];
let sum = arr.reduce((prev, curr) => prev + curr, 0)
// sum: 10
Above the reduce()
method is passed a callback with prev
, the previous result and curr
as the current item in the array. The callback ends up returning prev + curr
. The second argument to reduce()
takes an initial value. The end result is 10
, all the values summed up. Consider this second example so you see how powerful reduce()
really is:
let objects = [{
name: 'Xena'
}, {
country: 'Greece'
}]
let mergedObject = objects.reduce((prev, curr) => {
return {
...prev,
...curr
}
}, {})
// { name: 'Xena', country: 'Greece' }
Summary
I've shown that there are quite a few looping constructs at your disposal in JavaScript. They do different things and correctly used they can make you quite efficient. There's no reason to fear using for-in
now that you know what it does, even though for-of
is probably what you want. Consider adding map()
or reduce()
to your tool belt, if you haven't already.
Top comments (0)