# Mixing Generators Into Iterators

A relevant ad will be displayed here soon. These ads help pay for my hosting.
You can support Pony Foo directly through Patreon or via PayPal.

As it turns out, iterators can be written using generators. This can lead to some interesting use cases. Read on to understand the synergistic properties between these two JavaScript iteration concepts.

Let’s do a quick recap of generators (read our primer on generators here). Generator functions return generator objects when invoked. A generator object has a `next` method, which returns the next element in the sequence. The `next` method returns objects with a `{ value, done }` shape.

The following example shows an infinite fibonacci number generator. We then instantiate a generator object and read the first eight values in the sequence.

``````function* fibonacci() {
let previous = 0
let current = 1
while (true) {
yield current
const next = current + previous
previous = current
current = next
}
}
const g = fibonacci()
console.log(g.next()) // <- { value: 1, done: false }
console.log(g.next()) // <- { value: 1, done: false }
console.log(g.next()) // <- { value: 2, done: false }
console.log(g.next()) // <- { value: 3, done: false }
console.log(g.next()) // <- { value: 5, done: false }
console.log(g.next()) // <- { value: 8, done: false }
console.log(g.next()) // <- { value: 13, done: false }
console.log(g.next()) // <- { value: 21, done: false }
``````

Iterators follow a similar pattern (you may read our primer on iterators here). They enforce a contract that dictates we should return an object with a `next` method. That method should return sequence elements following a `{ value, done }` shape. The following example shows a `fibonacci` iterable that’s a rough equivalent of the generator we were just looking at.

``````const fibonacci = {
[Symbol.iterator]() {
let previous = 0
let current = 1
return {
next() {
const value = current
const next = current + previous
previous = current
current = next
return { value, done: false }
}
}
}
}
const sequence = fibonacci[Symbol.iterator]()
console.log(sequence.next()) // <- { value: 1, done: false }
console.log(sequence.next()) // <- { value: 1, done: false }
console.log(sequence.next()) // <- { value: 2, done: false }
console.log(sequence.next()) // <- { value: 3, done: false }
console.log(sequence.next()) // <- { value: 5, done: false }
console.log(sequence.next()) // <- { value: 8, done: false }
console.log(sequence.next()) // <- { value: 13, done: false }
console.log(sequence.next()) // <- { value: 21, done: false }
``````

Let’s reiterate. An iterable should return an object with a `next` method: generator functions do just that. The `next` method should return objects with a `{ value, done }` shape: generator functions do that too. What happens if we change the `fibonacci` iterable to use a generator function for its `Symbol.iterator` property? As it turns out, it just works.

The following example shows the iterable `fibonacci` object using a generator function for its iterator. Note how that iterator has the exact same contents as the `fibonacci` generator function we saw earlier. We can use `yield`, `yield*`, and all of the semantics found in generator functions hold.

``````const fibonacci = {
* [Symbol.iterator]() {
let previous = 0
let current = 1
while (true) {
yield current
const next = current + previous
previous = current
current = next
}
}
}
const g = fibonacci[Symbol.iterator]()
console.log(g.next()) // <- { value: 1, done: false }
console.log(g.next()) // <- { value: 1, done: false }
console.log(g.next()) // <- { value: 2, done: false }
console.log(g.next()) // <- { value: 3, done: false }
console.log(g.next()) // <- { value: 5, done: false }
console.log(g.next()) // <- { value: 8, done: false }
console.log(g.next()) // <- { value: 13, done: false }
console.log(g.next()) // <- { value: 21, done: false }
``````

Meanwhile, the iterable protocol also holds up. To verify that you might use a construct like `for..of`, instead of manually creating the generator object. The following example uses `for..of` and introduces a circuit breaker to prevent an infinite loop from crashing the program.

``````for (const value of fibonacci) {
console.log(value)
if (value > 20) {
break
}
}
// <- 1
// <- 1
// <- 2
// <- 3
// <- 5
// <- 8
// <- 13
// <- 21
``````

This was a fun trick. What would you use it for in a real-world program?

Liked the article? Subscribe below to get an email when new articles come out! Also, follow @ponyfoo on Twitter and @ponyfoo on Facebook.

Yimi wrote

I don’t know what to do with that knowledge but I love it!

John Doe wrote

The syntax of this code is really hard to understand.

``````const fibonacci = {
[Symbol.iterator]() {
let previous = 0
``````

Care to elaborate on that?

Nicolás Bevacqua wrote

That’s a `const` binding named `fibonacci`, with a `Symbol` property that’s assigned as a computed property name and that’s also using the method definition shorthand syntax, followed by the method body and a `let` binding named `previous` which is assigned an initial value of `0`.

Oh, I also have a book on the subject! It’s free to read online. Hope that helps.

John Doe wrote

OK thanks a lot for the fast answer; this is more or less what I inferred should be the case, using lowest-denominator syntax:

``````const iterator_key = Symbol.iterator;
cont fibonacci = {};
fibonacci[ iterator_key ] = function () {
let previous = 0;
...
};

``````

I’m not sure I’m overly happy with that “you can leave out the function keyword in this case”. Sure it makes writing things easier and does remove some clutter. But it also makes the syntax more complex without introducing a new feature. Besides, parens and braces are also used for other things, so there’s still no unique syntax. Well, I guess you get used to it.

Moritz Kröger wrote

A bit late to the party, but you can also keep the function keyword in the previous example and have it more expressive.

``````const fibonacci = {
[Symbol.iterator]: function () {
let previous = 0
...
}
}
``````
Andrzej Kopeć wrote

Hi!

I’ve been always thinking that generators are just a syntactic sugar for creating own iterators but your post suggests that generator object and real iterator differ (a lot?). So what are the differences between them?