Use the For-Of Loop to Iterate Through JavaScript Iterable Objects
Tags: javascript, beginners, tutorial, oop
Published: 2019-12-31 02:07:52

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

Starting with ES2015, we have a new kind of loop to loop over iterable objects. The new `for...of` loop is a new kind of loop that lets us loop over any iterable objects without using a regular `for` loop, `while` loop, or using the `forEach` function in the case of arrays. It can be used directly to iterate through any iterable objects, which include built-in objects like Strings, Arrays, array-like objects like `arguments` and `NodeList`, `TypedArray`, `Map`, `Set` and any user-defined iterables. User-defined iterables include entities like generators and iterators.

If we want to use the `for...of` loop to iterate over an iterable object, we can write it with the following syntax:

```javascript
for (variable of iterable){  
  // run code  
}
```

The `variable` in the code above is the variable representing each entry of the iterable object that is being iterated over. It can be declared with `const` , `let` or `var` . The `iterable` is the object where the properties are being iterated over.

For example, we can use it to iterate over an array-like in the following code:

```javascript
const arr = [1,2,3];  
  
for (const num of arr) {  
  console.log(num);  
}
```

The code above, the `console.log` statements will log 1, 2, and 3. We can replace `const` with `let` if we want to assign the variable we used for iteration in the `for...of` loop. For example, we can write:

```javascript
const arr = [1,2,3];  
  
for (let num of arr) {  
  num *= 2 ;   
  console.log(num);  
}
```

The code above, the `console.log` statements will log 2, 4, and 6 since we used the `let` keyword to declare the `num` so we can modify `num` in place by multiplying each entry by 2. We cannot reassign with `const` so we have to use `let` or `var` to declare the variable we want to modify in each iteration.

We can also iterate over strings. If we do that we all get each character of the string in each iteration. For example, if we have the code below:

```javascript
const str = 'string';  
  
for (const char of str) {  
  console.log(char);  
}
```

Then we get the individual characters of `'string'` logged in each line.

Likewise, we can iterate over TypedArrays, which contains binary data represented by a series of numbers in hexadecimal format. For example, we can write the following code:

```javascript
const arr = new Uint8Array([0x00, 0x2f]);  
  
for (const num of arr) {  
  console.log(num);  
}
```

In the example above, `console.log` will log 0 and 47. Note that the logged value is in decimal format but the entered value is in hexadecimal format.

If we iterate over Maps, then we get each entry of the Map. For example, we can write the following code to iterate over Maps:

```javascript
const map = new Map([['a', 2], ['b', 4], ['c', 6]]);  
  
for (const entry of map) {  
  console.log(entry);  
}
```

If we log the entries, we get `['a', 2]`, `['b', 4]`, and `['c', 6]` . Maps consist of key-value pairs as their entries. When we iterate over a Map, we get the key as the first element and the value as the second element is each entry. To get the key and value of each entry into its own variable we can use the destructuring operator, like in the following code:

```javascript
const map = new Map([['a', 2], ['b', 4], ['c', 6]]);  
  
for (const [key, value] of map) {  
  console.log(key, value);  
}
```

Then when we log the entries, we get `'a' 2`, `'b' 4`, and `'c' 6`.

We can also use the `for...of` loop for Sets. For example, we can loop over a Set by doing the following:

```javascript
const set = new Set([1, 1, 2, 3, 3, 4, 5, 5, 6]);  
  
for (const value of set) {  
  console.log(value);  
}
```

We set that we get 1, 2, 3, 4, 5, and 6 logged since the Set constructor automatically eliminates duplicate entries by keeping the first occurrence value in the Set and discarding the later occurrence of the same value.

The `for...of` loop also works for iterating over the `arguments` object, which is a global object that has the arguments that were passed into the function when the function is called. For example, if we write the following code:

```
(function() {  
  for (const argument of arguments) {  
    console.log(argument);  
  }  
})(1, 2, 3, 4, 5, 6);
```

We see that we see 1, 2, 3, 4, 5, and 6 logged since this is what we passed in when we called the function. Note that this only works for regular functions since the context of `this` has to be changed to the function being called instead of `window`. Arrow functions don’t change the content of `this`, so we won’t get the correct arguments when we run the same loop inside an arrow function.

Also, we can iterate over a list of DOM Node objects, called a `NodeList` . For example, is a browser implemented the `NodeList.prototype[Symbol.iterator]` , then we can use the `for...of` loop like in the following code:

```javascript
const divs = document.querySelectorAll('div');  
  
for (const div of divs) {  
  console.log(div);  
}
```

In the code above we logged all the `div` elements that are in the document.

With `for...of` loops, we can end the loop by using the `break` , `throw` or `return` statements. The iterator will close in this case, but the execution will continue outside the loop. For example, if we write:

```javascript
function* foo(){   
  yield 'a';   
  yield 'b';   
  yield 'c';   
};   
  
for (const o of foo()) {   
  console.log(o);   
  break;  
}

console.log('finished');
```

In the code above, we only log ‘a’ because we have a break statement at the end of the `for...of` loop, so after the first iteration, the iterator will close and the loop ends.


We can loop over generators, which are special functions that return a generator function. The generator function returns the next value of an iterable object. It’s used for letting us iterate through a collection of objects by using the generator function in a `for...of` loop.

We can also loop over a generator that generates infinite values. We can have an infinite loop inside the generator to keep returning new values. Because the `yield` statement doesn’t run until the next value is requested, we can keep an infinite loop running without crashing the browser. For example, we can write:

```javascript
function* genNum() {  
  let index = 0;  
  while (true) {  
    yield index += 2;  
  }  
}

const gen = genNum();  
for (const num of gen) {  
  console.log(num);  
  if (num >= 1000) {  
    break;  
  }  
}
```

If we run the code above, we see that we get numbers from 2 to 1000 logged. Then `num` is bigger than 1000 so that the `break` statement is run. We cannot reuse the generator after it’s closed, so if we write something like the following:

```javascript
function* genNum() {  
  let index = 0;  
  while (true) {  
    yield index += 2;  
  }  
}

const gen = genNum();  
for (const num of gen) {  
  console.log(num);  
  if (num >= 1000) {  
    break;  
  }  
}

for (const num of gen) {  
  console.log(num);  
  if (num >= 2000) {  
    break;  
  }  
}
```

The second loop won’t run because the iterator that was generated by the generator is already closed by the first loop with the `break` statement.

We can iterate over other iterable objects that have the method denoted with the `Symbol.iterator` Symbol defined. For example, if we have the following iterable object defined:

```javascript
const numsIterable = {  
  [Symbol.iterator]() {  
    return {  
      index: 0,  
      next() {  
        if (this.index < 10) {  
          return {  
            value: this.index++,  
            done: false  
          };  
        }  
        return {  
          value: undefined,  
          done: true  
        };  
      }  
    };  
  }  
};
```

Then we can run the loop below to show log the generated results:

```javascript
for (const value of numsIterable) {  
  console.log(value);  
}
```

When we run it, should see 0 to 9 logged when `console.log` is run in the loop above.

It’s important that we don’t confuse the `for...of` loop with the `for...in` loop. The `for...in` loop if for iterating over the top-level keys of objects including anything up the prototype chain, while the `for...of` loop can loop over any iterable object like arrays, Sets, Maps, the `arguments` object, the `NodeList` object, and any user-defined iterable objects.

For example, if we have something like:

```javascript
Object.prototype.objProp = function() {};  
Array.prototype.arrProp = function() {};
const arr = [1, 2, 3];  
arr.foo = 'abc';for (const x in arr) {  
  console.log(x);  
}
```

Then we get 0, 1, 2, ‘foo’, ‘arrProp’ and ‘objProp’ logged, which are keys of objects and methods that are defined for the `arr` object. It included all properties and methods up to the prototype chain. It inherited all properties and methods from Object and Array that were added to Object and Array’s prototype so we get all the things in the chain inheritance in the `for...in` loop. Only enumerable properties are logged in the `arr` object in arbitrary order. It logs index and properties we defined in `Object` and `Array` like `objProp` and `arrProp`.

To only loop through properties that aren’t inheritance from an object’s prototype, we can use the `hasOwnPropetty` to check if the property is defined on the own object:

```javascript
Object.prototype.objProp = function() {};  
Array.prototype.arrProp = function() {};
const arr = [1, 2, 3];  
arr.foo = 'abc';for (const x in arr) {  
  if (arr.hasOwnProperty(x)){  
    console.log(x);  
  }  
}
```

`objProp` and `arrProp` are omitted because they’re inherited from `Object` and `Array` objects respectively.

The `for...of` loop is a new kind of loop that lets us loop over any iterable objects without using a regular `for` loop, `while` loop, or using the `forEach` function in the case of arrays. It can be used directly to iterate through any iterable objects, which include built-in objects like Strings, Arrays, array-like objects like `arguments` and `NodeList`, `TypedArray`, `Map`, `Set` and any user-defined iterables. User-defined iterables include entities like generators and iterators. This is a handy loop because it lets us over any iterable object rather than just arrays. Now we have a loop statement that works with iterable object.