What are Iterators?

Iterators are just objects with a specific interface designed for iteration. All iterator objects have a next() method that returns a result object. The result object has two properties: value, which is the next value, and done, which is a boolean that’s true when there are no more values to return. The iterator keeps an internal pointer to a location within a collection of values and with each call to the next() method, it returns the next appropriate value.

If you call next() after the last value has been returned, the method returns done as true and value contains the return value for the iterator. That return value is not part of the data set, but rather a final piece of related data, or undefined if no such data exists. An iterator’s return value is similar to a function’s return value in that it’s a final way to pass information to the caller.

With that in mind, creating an iterator using ECMAScript 5 is fairly straightforward:

  1. function createIterator(items) {
  2. var i = 0;
  3. return {
  4. next: function() {
  5. var done = (i >= items.length);
  6. var value = !done ? items[i++] : undefined;
  7. return {
  8. done: done,
  9. value: value
  10. };
  11. }
  12. };
  13. }
  14. var iterator = createIterator([1, 2, 3]);
  15. console.log(iterator.next()); // "{ value: 1, done: false }"
  16. console.log(iterator.next()); // "{ value: 2, done: false }"
  17. console.log(iterator.next()); // "{ value: 3, done: false }"
  18. console.log(iterator.next()); // "{ value: undefined, done: true }"
  19. // for all further calls
  20. console.log(iterator.next()); // "{ value: undefined, done: true }"

The createIterator() function returns an object with a next() method. Each time the method is called, the next value in the items array is returned as value. When i is 3, done becomes true and the ternary conditional operator that sets value evaluates to undefined. These two results fulfill the special last case for iterators in ECMAScript 6, where next() is called on an iterator after the last piece of data has been used.

As this example shows, writing iterators that behave according to the rules laid out in ECMAScript 6 is a bit complex.

Fortunately, ECMAScript 6 also provides generators, which make creating iterator objects much simpler.