es6-guide

iterators

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
}