Iterators & Generators
Iterators and Generators bring the concept of iteration directly into the core language and provide a mechanism for customizing the behavior of for...of loops.
Iterators
In JavaScript an iterator is an object which defines a sequence and potentially a return value upon its termination. Specifically, an iterator is any object which implements the Iterator Protocol by having a next() method that returns an object with two properties:
value | The next value in the iteration sequence. |
---|---|
done | This is true if the last value in the sequence has already been consumed. If value is present alongside done, it is the iterator's return value. |
Once created, an iterator object can be iterated explicitly by repeatedly calling next(). Iterating over an iterator is said to consume the iterator, because it is generally only possible to do once. After a terminating value has been yielded additional calls to next() should continue to return {done: true}.
The most common iterator in JavaScript is the Array iterator, which returns each value in the associated array in sequence.
While it is easy to imagine that all iterators could be expressed as arrays, this is not true. Arrays must be allocated in their entirety, but iterators are consumed only as necessary. Because of this, iterators can express sequences of unlimited size, such as the range of integers between 0 and Infinity.
Here is an example which can do just that. It allows creation of a simple range iterator which defines a sequence of integers from start (inclusive) to end (exclusive) spaced step apart. Its final return value is the size of the sequence it created, tracked by the variable iterationCount.
Iterator Response
Generator Functions
While custom iterators are a useful tool, their creation requires careful programming due to the need to explicitly maintain their internal state. Generator functions provide a powerful alternative: they allow you to define an iterative algorithm by writing a single function whose execution is not continuous. Generator functions are written using the function* syntax.
When called, generator functions do not initially execute their code. Instead, they return a special type of iterator, called a Generator. When a value is consumed by calling the generator's next method, the Generator function executes until it encounters the yield keyword.
The function can be called as many times as desired, and returns a new Generator each time. Each Generator may only be iterated once.
We can now adapt the example from above. The behavior of this code is identical, but the implementation is much easier to write and read.
yield | The yield operator is used to pause and resume a generator function. |
---|
Iterables
An object is iterable if it defines its iteration behavior, such as what values are looped over in a for...of construct. Some built-in types, such as Array or Map, have a default iteration behavior, while other types, such as Object do not.
In order to be iterable, an object must implement the @iterator method. This means that the object (or one of the objects up its prototype chain) must have a property with a Symbol.iterator key.
It may be possible to iterate over an iterable more than once, or only once. It is up to the programmer to know which is the case.
Iterables which can iterate only once, such as Generators customarily return this from their @iterator method, whereas iterables which can be iterated many times must return a new iterator on each invocation of @iterator.
Generator Response
Iteration: "+ iterationCount +" - Item: "+ itItem; } divResult.innerHTML = returnStr; }