For of loops in Javascript one loop to rule them all
Tags: javascript
Published: 2020-03-17 20:10:52

---
title: For of loops in Javascript one loop to rule them all
published: true
date: 2020-03-17 19:04:37 UTC
tags: javascript
canonical_url: https://www.jonathancreamer.com/for-of-loops-in-javascript-one-loop-to-rule-them-all/
---

 ![For of loops in Javascript one loop to rule them all](https://www.jonathancreamer.com/content/images/2020/03/IMG_0533-EFFECTS.jpg)

For the longest time, `for in` and `for` were the main loops you could use to iterate over collections of things in JavaScript. Then we got some fancy array methods like `forEach`, `map`, `filter`, etc. It starts to get a bit confusing of when to use each loop type. For example, you can't use `for in` on array's, only on objects. Then, how do I loop over an object? Well, you can use `for in`, but only if you check `hasOwnProperty` or whatever, or use...

```
Object.keys(obj).map((key) => {
  const value = map[key];
});
```

Which is all weird because you have to get the keys, then grab the value, etc.

Now, we have a new thing as of ES6 called `for of`. It's becoming more and more used as knowledge of how to use it has grown, but there's still occasional confusion around how/when to use it. Below is a quick cheatseat of some usages of `for of`, one loop to rule them all.

### Arrays

```
const arrayOfStuff = ['thing one', 'thing two', 'thing three'];

for (const thing of arrayOfStuff) {
  console.log(thing);
}

```

For arrays, it's pretty simple. It looks like a `for in`, but you can't `for in` an array. The point here is, the `thing` becomes each item in the array.

### Arrays of Objects

```
const arrayOfObjectsOfStuff = [{ name: 'thing one' }, {name: 'thing two' }, { name: 'thing three' }];

for (const { name } of arrayOfObjectsOfStuff) {
  console.log(name);
}
```

Here you'll notice when iterating an array of objects, you can utilize destructuring to pull the value of the key `name` off of every item in the array. Note, the descructuring here uses `{}`'s because we're descructuring an object, vs `[]` in the case of desctructuring an array.

### Objects

```
const userMap = {
  '123': 'user 1',
  '456': 'user 2',
  '789': 'user 3',
};

for (const [id, name] of Object.entries(userMap)) {
  console.log(id, name);
}
```

Things get even cooler here now, thanks to the magic of `Object.entries`. Object.entries returns an array of key value pairs, so in this case basically...

```
[
  [123, 'user 1'],
  [456, 'user 2'],
  [789, 'user 3'],
]
```

So, you're in one line converting the object to an array of key value arrays, and then using destructuring to get the id, and name values!

### Maps 

```
const actualMapOfUsers = new Map();

actualMapOfUsers.set('123', 'user 1');
actualMapOfUsers.set('456', 'user 2');
actualMapOfUsers.set('7899', 'user 3');

for (const [id, name] of Array.from(actualMapOfUsers)) {
  console.log(id, name);
}

```

With ES6 `Map` objects, you can just use the `Array.from` method to convert the `Map` into, you guessed it, an array of key values pairs again.

### Promises

```
const getUser = async (name) => {
  const response = await fetch(`https://api.github.com/users/${name}`);
  const json = await response.json();
  return json;
};

const arrayOfPromises = [];

const usernames = ['jcreamer898', 'kwelch', 'AlexSwensen'];
for (const user of usernames) {
  arrayOfPromises.push(getUser(user));
}

Promise.all(arrayOfPromises).then((users) => {
  for (const user of users) {
    console.log(user.name);
  }
});
```

The final crazy cool thing you can do is handle promises or async await inside of `for of` loops. In the above example, we're actually creating an array of promises which we then resolve with `Promise.all`, so this will add a bunch of stuff into the event loop and then once they're all resolved, call the `.then` on the `Promise.all`.

Note in this case, there's no use of async / await, so the code will transpile to much less than that of the code that would require babel polyfill, etc from using async await. That said, you probably already have a polyfill like babel installed, so alternatively you can still async/await the `Promise.all` with...

```
const main = async () => {
    const users = await Promise.all(arrayOfPromises);
};
```

The other option is to use `await` in an `async` function and actually `await` each response.

```
const getUser = async (name) => {
  const response = await fetch(`https://api.github.com/users/${name}`);
  const json = await response.json();
  return json;
};

const getUsers = async () => {
    const users = [];
    const usernames = ['jcreamer898', 'kwelch', 'AlexSwensen'];

    for (const name of usernames) {
      const user = await getUser(name);
      users.push(user);
    }

    return users;
};

const main = async () => {
  await getUsers();
};
```

In this case the code will pause and wait for each `getUser` response to come back before moving on to the next one.

Here is a code sandbox where you can see all of this running!

<!--kg-card-begin: html--><iframe src="https://codesandbox.io/embed/suspicious-pond-xzc8i?expanddevtools=1&amp;fontsize=14&amp;hidenavigation=1&amp;module=%2Fsrc%2Findex.js&amp;theme=dark" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="suspicious-pond-xzc8i" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe><!--kg-card-end: html-->

Hopefully this article helps clear up any confusion in `for of` loops going forward.