Generator函数的基本概念与使用

81 阅读2分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

Generator函数是ES6引入的,主要用于异步编程,Generator最大特点就是可以交出函数的执行权(即暂停执行)

Generator函数与普通函数的区别

  1. function关键字与函数名之间有一个星号
  2. Generator函数体内部使用yield语句,定义不同的内部状态(函数内部的值,在不同的时候,是不一样的)

本质上,整个Generator函数就是一个封装的异步任务,或者说是异步任务的容器。

最简单的Generator函数

使用.next()方法让它动起来,可以把next理解为是一个“启动方法”,作用是分阶段地执行Generator函数

每次调用.next()方法,会返回一个对象,表示当前阶段的信息,value属性、done属性

done属性的值有true和false,true表示函数执行完了,false表示函数没执行完

  function* fn() {
    yield "a";
    yield "b";
    yield "c";
    return "d";
  }
  let _fn = fn(); // 调用函数,返回一个迭代器对象
  console.log(_fn.next());   // {value: 'a', done: false}
  console.log(_fn.next());   // {value: 'b', done: false}
  console.log(_fn.next());   // {value: 'c', done: false}
  console.log(_fn.next());   // {value: 'd', done: true}
  console.log(_fn.next());   // {value: undefined, done: true}

迭代器之间作用域独立

注:yield只能用在Generator函数里,普通函数不行

function* fn() {
  var _n = 1;
  yield ++_n;
  yield ++_n;
  yield ++_n;
}
var aa = fn(); // aa为迭代器1的引用
var bb = fn(); // bb为迭代器2的引用
console.log(aa.next()); // {value: 2, done: false}
console.log(aa.next()); // {value: 3, done: false}
console.log(bb.next()); // {value: 2, done: false}
console.log(aa.next()); // {value: 4, done: false}

从上面aa、bb两个迭代器的运行结果来看,每个迭代器之间是相互独立的,作用域独立。

每当你调用了一个迭代器内部的.next()方法,Generator函数内部的指针,就是从上一次停下的地方,继续运行,直到遇到下一个yield语句

next方法传参

Generator函数中的next方法可以接收参数

  • 传入的参数,其实是把上一个yield语句的返回值给覆盖了
  • 第一个next方法其实是启动器,在它之前没有yield语句,给第一个next方法传参没意义
function* fn() {
  var _n = 1;
  var _v = yield _n + 22;
  console.log("aa", _v);
  yield ++_n;
  yield ++_n;
}
var _fn = fn();
console.log(_fn.next()); // {value: 23, done: false}
_fn.next("abc"); // aa abc
console.log(_fn.next()); // {value: 3, done: false}

这个例子,是最能说明Generator函数的用途的例子,就是可以通过next方法,去分阶段的注入数据,让函数分阶段的给出不同的返回值

for...of

Generator函数,支持for of 循环,用来迭代Generator函数在执行时,生成的那个迭代对象

function* fn() {
  yield "a";
  yield "b";
  yield "c";
  return "d";
}
var _fn = fn();
for (var i of _fn) {
  console.log(i); // 依次输出 a b c
}