ES6 — iterators

Let’s talk about ECMAScript 2015



iterator & iterable

An iterator is an object with a next method that returns { done, value } tuples.

ES6 gives us a pattern for creating custom iterators and it has a similar implementation to Java Iterable or .NET IEnumerable. It has also built-in iterables: String, Array, TypedArray, Map and Set. An iterator object can be any object with a next() method.

Iterable is an object which has [Symbol.iterator]() method inside.
Symbol is in turn an unique and immutable data type which can be used as an identifier for object properties — no equivalent in ES5.
// Symbol
let s1 = Symbol('abc');
let s2 = Symbol('abc');
console.log(s1 !== s2); // true
console.log(typeof s1); // 'symbol'
let obj = {};
obj[s1] = 'abc';
console.log(obj); // Object { Symbol(abc): 'abc' }

Let’s see a simple iterator written from scratch, which allows us to iterate through random numbers which are dynamically generated by next() method. A function returning iterable object take one argument (items) which is used to determine if the iterator should stop and returns done = true.

let random1_10 = function (items = 1) {
return {
[Symbol.iterator]() {
let cur = 0;
return {
next() {
let done = cur === items,
random = Math.floor(Math.random() * 10) + 1;
++cur;
return {
done: done,
value: random
}
}
}
}
};
};
for (let n of random1_10(5)) {
console.log(n); // prints 5 random numbers
}

Every time for-of loop call next() method, an iterator generate a random number and returns it to the loop.

If the iterator returns done = true, you can omit value, so the result will be
{ done: true }
let random1_10 = function (items = 1) {
return {
[Symbol.iterator]() {
let cur = 0;
return {
next() {
if (cur === items) {
return {
done: true
}

}
          ++cur;
return {
done: false,
value: Math.floor(Math.random() * 10) + 1
}
}
}
}
};
};
for (let n of random1_10(5)) {
console.log(n); // prints 5 random numbers
}

for-of loop

ES6 has a new loop — for-of. It works with iterables. Let’s look at his signature:

for (LET of ITERABLE) {
CODE BLOCK
}

It’s similar to for-in loop, which can be used to iterate through object properties (plain old Objects).

Arrays in ES6 are iterable by default, so we finally can use for-of for looping over the elements.

const arr = [1, 2, 3, 4, 5];
for (let item of arr) {
console.log(item); // 1
// 2
// 3
// 4
// 5
}

Inside the for-of loop, we can even use a break, continue and return.

const arr = [1, 2, 3, 4, 5];
for (let item of arr) {
if (item > 4) {
break;
}
if (0 !== item % 2) {
continue;
}
console.log(item); // 2
// 4
}



Whole series is also available as an ebook. I published it on leanpub.com

Future is bright!

Show your support

Clapping shows how much you appreciated Maciej Rzepiński’s story.