Traversing collections of objects is an amazingly common problem. So much so that many languages provide for special constructs just for moving through collections. For example C# has a foreach
loop and Python has for x in
. These looping constructs are frequently built on top of an iterator. An iterator is a pattern that provides a simple method for selecting, sequentially, the next item in a collection.
The interface for an iterator looks like this:
interface Iterator{ next(); }
In the land of Westeros there is a well-known sequence of people in line for the throne in the very unlikely event that the king was to die. We can set up a handy iterator over the top of this collection and simply call next
on it should the ruler die:
class KingSuccession { constructor(inLineForThrone) { this.inLineForThrone = inLineForThrone; this.pointer = 0; } next() { return this.inLineForThrone[this.pointer++]; } }
This is primed with an array and then we can call it:
var king = new KingSuccession(["Robert Baratheon" ,"JofferyBaratheon", "TommenBaratheon"]); king.next() //'Robert Baratheon' king.next() //'JofferyBaratheon' king.next() //'TommenBaratheon'
An interesting application of iterators is to not iterate over a fixed collection. For instance an iterator can be used to generate sequential members of an infinite set like the fibonacci sequence:
class FibonacciIterator { constructor() { this.previous = 1; this.beforePrevious = 1; } next() { var current = this.previous + this.beforePrevious; this.beforePrevious = this.previous; this.previous = current; return current; } }
This is used like so:
var fib = new FibonacciIterator() fib.next() //2 fib.next() //3 fib.next() //5 fib.next() //8 fib.next() //13 fib.next() //21
Iterators are handy constructs allowing for exploring not just arrays but any collection or even any generated list. There are a ton of places where this can be used to great effect.
Iterators are so useful that they are actually part of the next generation of JavaScript. The iterator pattern used in ECMAScript 2015 is a single method that returns an object that contains done
and value
. done
is true
when the iterator is at the end of the collection. What is nice about the ECMAScript 2015 iterators is that the array collection in JavaScript will support the iterator. This opens up a new syntax which can largely replace the for
loop:
var kings = new KingSuccession(["Robert Baratheon" ,"JofferyBaratheon", "TommenBaratheon"]); for(var king of kings){ //act on members of kings }
Iterators are a syntactic nicety that has long been missing from JavaScript. Another great feature of ECMAScript-2015 are generators. This is, in effect, a built in iterator factory. Our fibonacci sequence could be rewritten like the following:
function* FibonacciGenerator (){ var previous = 1; var beforePrevious = 1; while(true){ var current = previous + beforePrevious; beforePrevious = previous; previous = current; yield current; } }
This is used like so:
var fib = new FibonacciGenerator() fib.next().value //2 fib.next().value //3 fib.next().value //5 fib.next().value //8 fib.next().value //13 fib.next().value //21