Javascript ECMAScript 2015 - Part 6: for of

written by Andreas Schipplock
Hurrr...for ... of loops are simple. But combined with generator functions they can turn into something more complex. I play with for ... of, generator functions and the new destructurizing feature of ecmascript 2016 6th edition.

00001: let makers = ['Audi', 'BMW', 'Mercedes', 'Ford'];
00002: 
00003: // how you would do it before es6
00004: for (let index in makers) {
00005:   console.log(makers[index]);
00006: }
00007: 
00008: // the new for .. of loop
00009: for (let maker of makers) {
00010:   console.log(maker);
00011: }
...of course you can do something like this
00001: makers.forEach((make) => {
00002:   console.log(make);
00003: });
...though you cannot return from this; it will loop all elements; no matter what you do :); you can use .every, or .some, of course...

or even shorter with an arrow function:
00001: makers.forEach(make => console.log(make));
However, if you want to iterate through all your object properties, you have several choices:
00001: let myCar = {
00002:   color: 'black',
00003:   make: 'BMW',
00004:   model: '3 Series',
00005:   mileage: 89000
00006: };
00007: 
00008: for (let key in myCar) {
00009:   console.log(myCar[key]);
00010: }
You cannot use "for .. of" here but you can convert your "object" to be compatible with "for .. of":
00001: let myOtherCar = {
00002:   color: 'green',
00003:   make: 'Ford',
00004:   model: 'Focus ST',
00005:   mileage: 12898,
00006:   [Symbol.iterator]() {
00007:     let properties = Object.keys(this);
00008:     let count = 0;
00009:     let done = false;
00010:     let next = () => {
00011:       if (count >= properties.length) {
00012:         done = true;
00013:       }
00014:       return {
00015:         done: done,
00016:         value: this[properties[count++]]
00017:       };
00018:     }
00019:     return { next };
00020:   }
00021: };
00022: 
00023: for (let property of myOtherCar) {
00024:   console.log(property);
00025: }
You will lose the ability to know the "key" so think twice if this is useful to you. I decided for myself I probably won't use this too often. You, however, gain the ability to use newer js features like destructurizing.
00001: let [ , make] = myOtherCar;
00002: console.log(make);
It's probably a good thing to have this built into the core language, though. The JS guys aren't stupid so there's a way to make the previous example a lot shorter: the following example makes use of a generator function:
00001: let mySuperCar = {
00002:   color: 'white',
00003:   make: 'Mini',
00004:   model: 'Cooper S',
00005:   mileage: 4588,
00006:   [Symbol.iterator]: function * () {
00007:     let properties = Object.keys(this);
00008:     for (let property of properties) {
00009:       yield this[property];
00010:     }
00011:   }
00012: };
00013: 
00014: for (let property of mySuperCar) {
00015:   console.log(property);
00016: }
That's much better. However, I had to use "function"; you have to write "function * ()", "function* ()" or "function *()".

for ... of combined with generator functions can turn into a powerful tool; especially if you want to hide implementation details. In my opinion this is a very nice new addition to javascript.

Andreas.