generator 和 yield
yield 的使用
generator 生成器
yield 可以使生成器返回多次
我习惯于从表象推测,不喜欢官方文档,写的字都认识,结果变成句子之后,就一句都看不懂
所以先举一个例子来看一下这个东西怎么玩儿
现在要生成自增的id
传统写法
var public_id = 0; function idUp () { public_id++; } idUp() // 需要新id时,调用 idUp ,使外部的变量+1 ,不管是使用变量,还是把id当做参数传入函数,函数内部无法保存id的当前状态(意思就是,如果没有外部变量也没有传参,函数就不知道id现在是多少).
使用生成器
function* idUp () { let id = 0; while (true) { yield id id++; } } var addId = idUp(); var newId = addId.next().value; // 需要新id时,使用 addId.next().value, 我们无需关心外部是否有id,因为id的状态在函数里面
注意两种方式的不同之处。
传统写法需要一个全局变量来保存id的状态,而使用 生成器 状态保存在生成器中(就这样理解吧,使用生成器的时候,就不需要定义全局变量了存储id了)。
大家也许会有疑问,使用 while(true) 都死循环了,这个 生成器真的能用么? 实则yield 会使 生成器暂停,一直到调用next()才会继续执行函数,直到遇到下一个yield或者return
写个简单的 生成器的例子来看一下
function *example () { let a = 0; console.log('第一次输出时a的值', a); yield a; a++; console.log('第二次输出时a的值', a); yield a; a++; console.log('第三次输出时a的值', a); return a; } var doExample = example(); // 此时并不会输出 , 个人理解是, 生成器在当做函数执行的时候,其实是返回了一个 生成器对象,或者说盒子比较恰当,生成器里面的真正需要执行的代码被放到了这个盒子里面。 console.log(doExample); // 输出 example {<suspended>} console.log(doExample.next()); // 输出 “第一次输出时a的值 0 ” 和 {value: 0, done: false} console.log(doExample.next()); // 输出 “第二次输出时a的值 1 ” 和 {value: 1, done: false} console.log(doExample.next()); // 输出 “第三次输出时a的值 2 ” 和 {value: 2, done: true} console.log(doExample.next()); // 输出 {value: undefined, done: true}
以上代码主要就是看一下 生成器的执行流程,主要是 通过这段代码来理解这样两个概念
1.yield 可以暂停生成器
2.next 继续执行生成器直到 遇到下一个yield或者return
现在可以理解上面使用whil(true)了,但是并不会导致死循环,因为程序的执行其实是控制在 生成器的next手里。
另外一个需要 特别说一下的知识点是 每次执行next返回的对象里面 的 done 代表了生成器是否执行完成。可以理解为后面是否还有yield 如果还有yield,则 done:false 如果没有yield了,则为 true
并且,当生成器执行到末尾的时候,既 done:true 的时候,再次执行 next ,并没有任何输出,且 value 变成了 undefined。这里为啥是 undefined 。再写一个例子。
function *test () { let a = 0; yield; a++; yield a; a++; return a; } var doTest = test(); console.log(doTest.next()); // 输出 {value: undefined, done: false} console.log(doTest.next()); // 输出 {value: 1, done: false} console.log(doTest.next()); // 输出 {value: 2, done: true}
console.log(doTest.next());
// 输出 {value: undefined, done: true}
比较和上一个例子的区别,第一次输出的 value 的值是 undefined ,因为代码中 yield 后面什么都没有。第二次value的值是1,因为代码中yield后面接了 a。 意思就是value里面的值是 yield 后面的东西。
所以,最后输出 undefined 是不是就理解了 (因为代码都跑完了,已经没有yield了,自然就不会再有值了,value自然就是空)
好了就说这么多了,还有更多坑,大家有兴趣的可以自己去踩踩。
。。。。