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自然就是空)

好了就说这么多了,还有更多坑,大家有兴趣的可以自己去踩踩。

。。。。

猜你喜欢

转载自www.cnblogs.com/tmbm/p/10827247.html
今日推荐