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
Well, generator functions are kind of special. They can accept and return values multiple times throughout its execution, while 'normal' functions can only accept a fixed set of parameters, and return a single value. In your first example they are used to pass data to the generator (passing parameters multiple times), while in the second example its the other way around (returning values a several times).
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.
I think what you're running into is the behavior of the post-increment operator, ie index++
. If you changed it to the pre-increment operator, ie ++index
, it will behave the way you're expecting.
The difference is that post-increment will add 1 to index
after the expression is evaluated. Pre-increment will add 1 to index
before the expression is evaluated, which I think is your goal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With