Monday, February 16, 2015

You’ll know you are looking at a generator, or more properly, a generator function, because a generator function contains an asterisk in the declaration.

function*() { }

Once you have a generator function, you can use the yield keyword inside to return multiple values to the caller.

let numbers = function*() { yield 1; yield 2; yield 3; };

But, the numbers don’t come back to the caller all at once. Internally, the runtime builds an iterator for you, so a caller can iterate through the results one by one. You can write a low level iterator and call *next* to move through each value, or use a *for of* loop.

let sum = 0; for(let n of numbers()) { sum += n; } expect(sum).toBe(6);

Going back to the classroom class we used in the last ES6 post, we can now make a classroom an iterable simply using *yield*.

class Classroom { constructor(...students) { this.students = students; } *[Symbol.iterator]() { for(let s of this.students) yield s; } } var scienceClass = new Classroom("Tim", "Sue", "Joy"); var students = []; for(let student of scienceClass){ students.push(student); } expect(students).toEqual(["Tim", "Sue", "Joy"])

Notice how the iterator method needs an asterisk before the opening square bracket. The syntax is quirky, but an asterisk is always required when defining a generator function, because generator functions need to behave differently than normal functions right from the start. That’s the topic for the next post in this series.