Generator的参数和返回值

最近在学ES6的知识,发现了一个很有趣,很神奇的东西,Generator函数。

写一个最简单的Generator函数,定义的时候比普通的函数多了一个*,然后使用yield和return向外输出信息。

调用的时候,先要执行Generator函数,例如var g1 = gen1(),这样,就会返回一个遍历器对象(Iterator Object),然后调用next()。

function* gen1() {
  yield 'hello';
  yield 'world';
  return '!!!';
}

var g1 = gen1();
g1.next()    //Object {value: "hello", done: false}
g1.next()    //Object {value: "world", done: false}
g1.next()    //Object {value: "!!!", done: true}
g1.next()    //Object {value: undefined, done: true}

每次调用next(),都会返回一个对象,value代表返回的值,done表示是否还能继续遍历。done为false表示还可以继续调用next(),为true,表示已经没有值可以返回了。比如第4个next(),value就为undefined

可见Generator函数是分段执行的,每次next()后都会暂停起来,等待下次next()


其实,生成遍历器对象(Iterator Object)的时候,还可以传递参数,比如

function* gen2(x){
  yield x + 2;
}

var g2=gen2(5);
g2.next();    //Object { value: 7, done: false }
g2.next();    //Object { value: undefined, done: true }

看代码,很容易理解哈,和正常的函数传递参数效果一样哈

那现在来点不容易理解的,将上面的代码稍微改改,看代码

function* gen3(x){
  var y = yield x + 2;
  var z = yield y;
  return z;
}

var g3=gen3(5);
g3.next();      //Object { value: 7, done: false }
g3.next(20);    //Object { value: 20, done: false }
g3.next();      //Object { value: undefined, done: true }

怎么样,看明白了么。为什么g3.next(20)输出的值是20呢?
按道理,g3.next(20)应该是yield y输出的,y应该和yield x+2有关系,应该是7才对呀
其实吧,var y = yield x + 2;,这里的y的值,并不取决于等号后面的值是多少,而是取决于下次调用next()传递的参数
因为第二次调用g3.next(20);传递的是20,所以,y的值就成了20,如果这里没有传值,那么就是undefined,就类似第3次调用next()


我当时也是这里看的有点疑惑,然后动手做了几个例子,加深理解,然后记录下来