i value in a
for loop. The term has mixed meanings but in this case we’re refering to the former, an object which gives us a consistent interface for iterating over a collection of some kind. If you’ve never used them before that might seem kind of silly. “If I need to loop over something I’m just going to loop over it!” For many use cases that’s totally fine. Where Iterator objects are useful is in situations where you might need to loop in an async fashion (stopping and restarting) or if you want to preclude an object from knowing too much about the inner workings of a collection.
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
Also Known As
The code for an Iterator should be pretty easy to grok if you’ve worked with loops before. Here is a simple example which returns an Iterator for looping over an Array by every third value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Our iterator has a handful of useful operations including
next will return the next value and advance the index by 3.
hasNext will check to see if calling
next will actually return an item. Good for indicating when we’ve reached the end of a collection.
rewind will reset the index to zero so we can loop over the collection again.
current will return the current item at the index without advancing the index.
Let’s put these into play to see how it works:
1 2 3 4 5 6
If we ran the above we’d see the following output in the console.
1 2 3 4 5
Since the iterator is mainting its own state if we need to stop iteration at any point we just don’t call
next. Using exclusively
for loops we’d have to check against a flag of some kind, store our current position and then rebuild the loop starting from that point.
Not just for Arrays
As I mentioned before the Iterator gives us a consistent interface for traversing a collection, which means it can iterate over any object. Calendar Dates, Linked Lists, Node Graphs, whatever! Here’s an example of an iterator that traverses a simple Hash.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Notice how the interface is identical to our previous Iterator? That’s one of the key aspects to this pattern: Regardless of the type of collection, we can define a consistent interface to loop through it. It also means that the client doesn’t need to know anything about the implementation of the actual collection, and by wrapping it in a closure we can prevent the client from editing the collection. Personally I like the idea of certain services handing out iterators rather than a wholesale dump of all the data. As always use whichever tool is appropriate for the context.
One quick note regarding Hashes. Previous versions of the ECMA spec did not require that Hash keys be kept in order. While most modern browsers do keep them in order there are some funky inconsistencies. For instance, if you write out the following Hash:
Google Chrome will swap the order of the keys such that they appear like this:
There are some interesting discussions on StackOverflow which cover this topic but it’s a bit outside the scope of this article. If you’re interested you can find them here:
1 2 3 4
The above script block will not work in Chrome but it should work in the latest version of Firefox. Note the
type attribute of the script tag which instructs the interpreter to handle the code as JS 1.7.
- Composite: Iterators are often applied to recursive structures such as Composites.
- Factory Method: Polymorphic iterators rely on factory methods to instantiate the appropriate Iterator subclass.
- Memento: Often used in conjunction with the Iterator pattern. An iterator can use a memento to capture the state of an iteration. The iterator stores the memento internally.
Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1994-10-31). Design Patterns: Elements of Reusable Object-Oriented Software. Pearson Education (USA).
Thanks for reading! If you have questions or feedback please leave a comment below. - Rob
You should follow me on Twitter here.