What is a Generator Function?
A generator function allows you to build custom iterators with ease. Generator functions are defined using the function*
syntax.
When called, a generator function doesn’t execute its body immediately. Instead, it returns a special iterator, known as the generator object. The generator function is executed when you call the object’s next()
method and this execution stops when first yield keyword is encountered, and returns an object containing two properties:
value
: the yielded valuedone
: a boolean indicating if the generator has finished execution When object’snext()
method is called again, it resume its execution from where it stopped. You can create multiple objects of a generator function, each maintaining its own state. Let’s dive into an example.
Iterating Over a Generator Object
You can iterate over a generator object in two ways:
- Using the spread
(...)
operator - Using a
for...of
loop Here’s an example:
Knowledge Check: What’s the Output?
Let’s test your knowledge with this question:
Challenge 1
Guess the output of the below code.
If you guessed [1, 2, 3], you’re correct!
The reason behind this behavior is that the return statement in a generator is treated differently. The spread operator and for…of loop collect only the yielded values (1, 2, and 3)
and stop once done: true
is encountered. The return
value (4) is ignored in the iteration process as return keyword returns object with done: true
.
Challenge 2
What do you think will happen here?
The output will be
This is because, when an iterator has been consumed (like in the first arr1
), it cannot be reused. You can, however, create a new generator object to start the iteration again.
Where it can be used?
Generator functions not just helps in building an iterator, but also provides a unique way to handle tasks that require pausing and resuming.
Now that you have a solid understanding of generator functions, let’s look at a few real-world scenarios where they can be used.
Finite State Machines
A state machine cycles through different states based on specific rules. Generators make it easy to switch between these states in a controlled manner without needing complex conditionals or manually tracking the current state. I have provided simple traffic signal as an example, but it can be used in many cases.
Iterator for data structures
If you are building custom data structure to handle business use cases, you can provide easy way to access the values by providing a iterator. In this example, I have used tree and iterating it as inorder traversal.
Conclusion
Generator functions are a truly versatile feature in JavaScript, letting you tackle a wide range of tasks with ease. Once you get comfortable with generators, you’ll find they can be a game-changer for handling iterative tasks in your projects.