Iterators and generators introduce the concept of iteration directly into the JavaScript language and provide a mechanism for customizing for...of loops.
Iterators
An iterator is an object that defines a sequence and returns a value after its termination. An iterator is an object that implements a next()
method with no arguments that return an object with at least the following 2 properties:
done
: A boolean value set to false if the iterator was able to produce the next value in the sequence. It is set to true if the iterator has completed its sequence.value
: A JavaScript value returned by the iterator. It's not required ifdone
istrue
.
function fibonacciIterator(limit = 10) {
let current = 1, next = 0;
let index = 1;
const iterator = {
next: function () {
if (index++ <= limit) {
[next, current] = [current + next, next];
return { value: current, done: false };
}
return { done: true };
}
};
return iterator;
}
const fb = fibonacciIterator(4);
console.log(fb.next()); // { value: 0, done: false }
console.log(fb.next()); // { value: 1, done: false }
console.log(fb.next()); // { value: 1, done: false }
console.log(fb.next()); // { value: 2, done: false }
console.log(fb.next()); // { done: true }
While custom iterators are useful, they require careful programming since we need to explicitly maintain it's internal state. This is where Generators come in to solve the problem.
Generators
Generators allow us to define an iterative algorithm inside a single function whose execution is not continuous. It generates a sequence of values instead of a single value, unlike normal functions. The Generator function returns a next()
method, which returns a value of type {value: any, done: boolean}
.
We can create a generator function by using the function*
syntax. Instead of using the return
keyword, we use the yield
keyword. When a generator function comes across the yield
keyword, it pauses itself, returning the value next to it. It returns a new generator each time it's called using next()
.
function* fibonacciGenerator(limit = 10) {
let current = 1, next = 0;
let index = 1;
while (index++ <= limit) {
[next, current] = [current + next, next];
yield current;
}
}
const fb = fibonacciGenerator(4);
console.log(fb.next()); // {value: 0, done: false}
console.log(fb.next()); // {value: 1, done: false}
console.log(fb.next()); // {value: 1, done: false}
console.log(fb.next()); // {value: 2, done: false}
console.log(fb.next()); // {value: undefined, done: true}