最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why is yield statement of a javascript generator function returning parameters of .next()? - Stack Overflow

programmeradmin0浏览0评论

I stumbled on generator functions on MDN and what puzzles me is the following example:

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

What I don't understand is why the yield statement which is the argument of console.log returns the parameter passed to the .next() method of the generator. Is this happening because an empty yield must return the value of the first parameter of the .next() method?

I have also tried some more examples, which seem to confirm the above statement like:

gen.next(1,2,3); // the printed value is 1, the 2 and 3 are ignored
// and the actual yielded value is undefined

Also is there a way to access the further parameters of the .next() method inside the body of the generator function?

Another thing I noticed is, while the yield statement is returning these values to the console.log they are actually not yielded as the output of the generator. I must say I find it very confusing.

I stumbled on generator functions on MDN and what puzzles me is the following example:

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

What I don't understand is why the yield statement which is the argument of console.log returns the parameter passed to the .next() method of the generator. Is this happening because an empty yield must return the value of the first parameter of the .next() method?

I have also tried some more examples, which seem to confirm the above statement like:

gen.next(1,2,3); // the printed value is 1, the 2 and 3 are ignored
// and the actual yielded value is undefined

Also is there a way to access the further parameters of the .next() method inside the body of the generator function?

Another thing I noticed is, while the yield statement is returning these values to the console.log they are actually not yielded as the output of the generator. I must say I find it very confusing.

Share Improve this question edited Aug 15, 2017 at 22:19 jakubiszon asked Aug 15, 2017 at 22:12 jakubiszonjakubiszon 3,5831 gold badge32 silver badges43 bronze badges 3
  • ...because that's what's supposed to happen? Why does this confuse you? – user2357112 Commented Aug 15, 2017 at 22:26
  • That's just what a yield expression evaluates to. – user2357112 Commented Aug 15, 2017 at 22:28
  • @user2357112 it confuses me because I do not see the parameter to be referenced in the above code. Having read the links from the answers it all makes sense now but when I first saw it I didn't understand it. As a side note, you can also do things like function* x() {yield yield yield;} – jakubiszon Commented Aug 15, 2017 at 22:35
Add a ment  | 

3 Answers 3

Reset to default 5

Great question. I think reading the MDN on the .next() method is most helpful. You can define the value you want to pass within the generator function itself (i.e. yield 1) or pass the value via next() by saying something like gen.next(1)

The next() method itself returns an Object, with the properties value and a boolean done which signifies whether the generator function is plete (i.e. exhausted of available outputs and will now output only undefined for a value).

That said, there are two ways to access / pass it that value.

https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next

The confusion es from the fact that yield and next have different syntaxes, while they actually do the same thing. Generator and its caller are symmetric (that's why they are called "co"-routines and not "sub"-routines). Both functions can be thought as connected by a munication channel, and can either do their job or sleep waiting for an ining message in the channel. The only difference is that the generator is initially asleep (that is, there's an implicit "listen" mand at the top of it), while the caller is initially awake.

Both yield and next do the same thing three things:

  • write its argument to the channel
  • fall asleep and listen for an ining message
  • emit the ining message as its value and wake up (that is, carry on with what's below them)

Illustration:

_ = console.log.bind(console)

function *gen() {
    _('gen: good morning')

    _('gen: sending hi')
    _('gen: zzz')
    p = yield 'hi'
    _('gen: awake! got', p)

    _('gen: now sending fine')
    _('gen: zzz')
    p = yield 'fine'
    _('gen: awake! got', p) // ***
}

function main() {

    var g = gen()

    _('main: sending knock knock')
    _('main: zzz')
    r = g.next('knock knock')
    _('main: awake! got', r)

    _('main: sending how r u')
    _('main: zzz')
    r = g.next('how r u')
    _('main: awake! got', r)
}

main()

Note that since write es before read, the very first message sent to the generator is lost. It's only used to wake up the generator. Also note how we've left the generator in the sleeping state, so the *** line is not reached.

This makes it quite clear:

[rv] = yield [expression];

expression Defines the value to return from the generator function via the iterator protocol. If omitted, undefined is returned instead.

rv Returns the optional value passed to the generator's next() method to resume its execution.

Basically you're printing out the parameter you've sent through to continue execution.

发布评论

评论列表(0)

  1. 暂无评论