初步探索Generator 函数1

145 阅读3分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

定义

什么是generator函数呢?在es6中这是一个新引入的函数,它可以通过yield关键字,把函数的执行流程挂起,为了改变执行流程提供了可能,从而为异步编程提供解决方案。

基本用法

generator函数的组成有两个区分于普通函数的部分:

  • 一是在function后面,函数名之前有个*;
  • 函数内部有yield表达式。 其中的*用来表示函数为generator函数,yield用来定义函数内部的状态。
function* func(){
    console.log("one");
    yield '1';
    console.log("two");
    yield '2'; 
    console.log("three");
    return '3';
}

执行机制

那么generator函数的调用有什么不一样呢?其实调用方法是一样的,在函数名字后面加上()即可,但是generator函数不会像普通函数一样立即执行,而是返回一个指向内部状态对象的一个指针,所以要调用遍历器对象Iterator的next方法,指针就会从函数的头部或者上一次停下来的地方开始执行了。

f.next();
//one
//{value:"1",done:false}
f.next();
//two
//{value:"2",done:false}
f.next();
//three
//{value:"3",done:true}
f.next();
//one
//{value:undefined,done:true}

我们分析一下上面的调用过程: 第一次调用 next 方法时,从 Generator 函数的头部开始执行,先是打印了 one ,执行到 yield 就停下来,并将yield 后边表达式的值 '1',作为返回对象的 value 属性值,此时函数还没有执行完, 返回对象的 done 属性值是 false。

第二次调用 next 方法时,同上步 。

第三次调用 next 方法时,先是打印了 three ,然后执行了函数的返回操作,并将 return 后面的表达式的值,作为返回对象的 value 属性值,此时函数已经结束,多以 done 属性值为true 。

第四次调用 next 方法时, 此时函数已经执行完了,所以返回 value 属性值是 undefined ,done 属性值是 true 。如果执行第三步时,没有 return 语句的话,就直接返回 {value: undefined, done: true}。

for...of 循环

由于 Generator 函数运行时生成的是一个 Iterator 对象,因此,可以直接使用 for...of 循环遍历,且此时无需再调用 next() 方法 这里需要注意,一旦 next() 方法的返回对象的 done 属性为 true,for...of 循环就会终止,且不包含该返回对象

{
  function* gen() {
    yield 1
    yield 2
    yield 3
    yield 4
    return 5
  }
  
  for(let item of gen()) {
    console.log(item)
  }
  
  // 1 2 3 4
}

Generator.prototype.return() Generator 函数返回的遍历器对象,还有一个 return 方法,可以返回给定的值(若没有提供参数,则返回值的value属性为 undefined),并且 终结 遍历 Generator 函数

{
  function* gen() {
    yield 1
    yield 2
    yield 3
  }

  let it = gen()

  it.next()             // {value: 1, done: false}
  it.return('ending')   // {value: "ending", done: true}
  it.next()             // {value: undefined, done: true}
}

 Generator 函数应用举例 应用一:假定某公司的年会上有一个抽奖活动,总共6个人可以抽6次,每抽一次,抽奖机会就会递减按照常规做法就需要声明一个全局的变量来保存剩余的可抽奖次数,而全局变量会造成全局污染,指不定什么时候就被重新赋值了,所以往往并不被大家推荐

{
  let count = 6  // 声明一个全局变量

  // 具体抽奖逻辑的方法
  function draw() {
    // 执行一段抽奖逻辑
    // ...
    // 执行完毕

    console.log(`剩余${count}次`)
  }

  // 执行抽奖的方法
  function startDrawing(){
    if(count > 0) {
      count--
      draw(count)
    }
  }


  let btn = document.createElement('button')
  btn.id = 'start'
  btn.textContent = '开始抽奖'
  document.body.appendChild(btn)

  document.getElementById('start').addEventListener('click', function(){
    startDrawing()
  }, false)

}

我们初步认识了generator函数的定义以及执行机制。后续我们会了解generator函数返回的遍历器对象的方法。望持续关注。

关注我的公众号,会有意外惊喜。

扫码_搜索联合传播样式-标准色版.png