ES6 Everyday: Generator Functions
Remember yesterday when I showed you how to write a function that would generate an iterator?
function getIterator()
{
var values = ['Alligator', 'Bear', 'Lion'];
var currIndex = 0;
return {
next: function() {
return currIndex >= values.length
? { done: true }
: { done: false, value: values[currIndex++] };
}
};
}
var myIterator = getIterator();
console.log(myIterator.next().value); // Alligator
console.log(myIterator.next().value); // Bear
console.log(myIterator.next().value); // Lion
console.log(myIterator.next().done); // true
Cool and all, but phew, that’s a lot to write.
Luckily, ES6 provides an easier way to write these functions that generate iterators. Actually, they are called generator functions and you define them using function*
:
function* myGeneratorFunction()
{
}
Within our generator function, we can use the yield
keyword to sequentially return values:
function* getIterator()
{
yield "Alligator";
yield "Bear";
yield "Lion";
}
var iterator = getIterator();
console.log(iterator.next().value); // Alligator
console.log(iterator.next().value); // Bear
console.log(iterator.next().value); // Lion
console.log(iterator.next().done); // true
These generator functions return a Generator object, an object that adheres to both the iterable and iterator protocols.
So, of course, we can use them in a for..of
loop:
function* getMenu()
{
yield "Steak";
yield "Mashed Potatoes";
yield "Porter";
}
for(let item of getMenu())
{
console.log(item); // Steak, Mashed Potatoes, Porter
}
And, if you’re wondering, yes, you can have anonymous generator functions too:
var getPalette = function*()
{
yield "Blue";
yield "Red";
yield "Orange";
}