Using ES6 generators in for loops
August 20, 2017 Leave a comment
Generator functions are a new feature in ES6. A generator is a function that can be entered multiple times and each time it will return something else. Generators are definitely strange at first. If you are familiar with the yield keyword in C# and how it is used then you’ll catch up with generators in ES6 quicker than others. I’m not aware of a similar feature in Java. Generators are strongly linked to iterators and arrays as we’ll see in a bit. I believe that Python uses yield as well.
The best thing is if we jump right into it.
The keyword to learn for generators is “yield” like in C#. A generator function must also be decorated with a star *. Here’s an example of a generator function:
function* programmingLanguages() { yield 'C#' yield 'Java' yield 'JavaScript' yield 'F#' }
Looks funny, right? Let’s try to execute the function:
programmingLanguages()
Nothing happens.
It turns out that we have to push a little harder and apply the next() function to get our lazy generator moving:
let langGenerator = programmingLanguages() let next = langGenerator.next()
Here comes the next interesting bit. langGenerator.next() will return – or yield – an object with two properties: value and done. Here’s what “next” looks like after the next() function was applied for the first time:
{"value":"C#","done":false}
Hmm, ok, let’s call next again:
{"value":"Java","done":false}
…and again…:
{"value":"JavaScript","done":false}
…almost there…:
{"value":"JavaScript","done":false}
…until we finally get the following:
{"done":true}
We still don’t know what on Earth that was but it was fun, wasn’t it? So we have a generator function called programmingLanguages() with a bunch of yield statements. Upon calling the function with next() we enter the function but exit it after yielding the first value “C#”. Then we call next() again, re-enter the function and continue where code execution was left off. We return “Java” this time. This entering-exiting cycle continues until we hit the last yield function and next() returns “done”.
We can use these properties to build a while-loop to iterate through the generator:
function iterateThroughLanguages() { let langGenerator = programmingLanguages() let next = langGenerator.next() while (!next.done) { console.log(next.value) next = langGenerator.next() } }
You’ll see that the boolean check for the while loop is based on the “done” property of the object returned by the generator.
However, there’s a much better way of iterating through generators using for-of loops:
for (let lang of programmingLanguages()) { console.log(lang) }
A for-of loop is a perfect match for iterating through generators in ES6.
View all posts related to JavaScript here.