Satya Sampathirao Satya Sampathirao - 2 months ago 5
Javascript Question

ES6 Generators: First call to next()

I was trying to understand how to use ES6 Generator functions. It seems pretty straight forward except for this one concept about making an empty next() function call while passing arguments. Here is the code I'm referring to from Mozilla docs.



function* logGenerator() {
console.log(yield);
console.log(yield);
console.log(yield);
}

var gen = logGenerator();

// the first call of next executes from the start of the function
// until the first yield statement

gen.next();
gen.next('pretzel'); // pretzel
gen.next('california'); // california
gen.next('mayonnaise'); // mayonnaise





From what I understand, the code is executed only until the 1st yield statement so nothing is returned and then for the 2nd time we call
next()
, the code is executed until the 2nd yield which includes the 1st yield line, hence
pretzel
is logged to console.

If this is the case, in the code mentioned below how is
0
getting logged in the 1st call to
next()
? I'm missing something here :(



function* idMaker() {
var index = 0;
while (index < 3)
yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined





Reference : Mozilla Documentation

Answer

Well, generator functions are kind of special. They have an input and output direction. In your first example they are used to pass data to the generator, while in the second example its the other way around.

Consider this example:

function* foo() {
    console.log("before a");

    var a = (yield 123);

    console.log("after a");

    yield (a * 2);

    console.log("end of function");
}

var bar = foo();

var x = bar.next(); // Runs until the first yield, prints 'before a'.
console.log(x.value); // 123
var y = bar.next(4); // Runs until the second yield, so prints 'after a'. 
console.log(y.value); // 8
var z = bar.next(); // prints 'end of function'.
console.log(z.done); // true

We pass in no data on the first next() call, letting it run until the first yield statement. Because of yield 123 the result of the call (x.value) is 123. The next time we call next() using 4 as parameter value we fill in local variable a inside the generator function. Code is executed until the next yield statement and returns the result of 8.

For the explanation why 0 instead of 1, see the other answer.

Comments