16-生成器(Generator)

88 阅读2分钟

生成器

  • 它是一个通过构造函数Generator创建的对象,js内部使用,但是我们不能取new
  • 生成器即是一个迭代器,说明有next对象
  • 又是一个可迭代对象

如何创建生成器

  • 生成器的创建,必须使用生成器函数 (Generator Function)
// => 这是个生成器函数,该函数一定返回一个生成器
function *method() {}

生成器函数内部是怎么执行的

  • 生成器函数内部是为了给生成器的每次迭代提供的数据
  • 每次调用生成器的next方法,将导致生成器函数运行到下一个yield关键字的一个位置
  • yield是一个关键字,只能在生成器函数内部使用,表示产生一个可迭代数据
function *test() {
  console.log("第一次运行");
  yield 1;
  console.log("第二次运行");
  yield 2;
  console.log("第三次运行")
}

// 这里没有运行,为了生成器的迭代做准备
const generator = test();
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

image.png

例子1

  • 这个就比之前自己写迭代器函数爽爆了
const arr = [1, 2, 3, 4];

function* createGenerator(arr) {
  for (const item of arr) {
    yield item;
  }
}
const iter1 = createGenerator(arr);
console.log(iter1.next());
console.log(iter1.next());
console.log(iter1.next());
console.log(iter1.next());
console.log(iter1.next());

image.png

斐波拉契队列重写

function *createFbGenerator() {
  let prev1 = 1,
      prev2 = 2,
      value,
      n = 1;//当前迭代的次数
  while(true) {
    value = n <= 2 ? 1: prev1 + prev2;
    yield value;
    prev2 = prev1;
    prev1 = value;
    n++;
  }
}
const iter = createFbGenerator();
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())

image.png

注意的细节

  • 生成器函数可以有返回值,返回值出现在第一次done为true时的value属性中
  • 调用生成器的next方法时,可以传递参数,传递的参数会交给yield表达式的返回值
  • 第一次调用next方式时,传参没有任何意义
  • 在生成器函数内部,可以调用其它生成器函数
function *test() {
  let info = yield 1;
  console.log(info);
  info = yield 2 + info;
  console.log(info);
  yield info;
}
const generator = test();
console.log(generator.next())
console.log(generator.next(5))// 把5传给第一个 yield
console.log(generator.next(9))// 把9传给第二个 yield
console.log(generator.next())

image.png

生成器里面的调用(集成)别的生成器

function * test1() {
    yield 'a';
    yield 'b';
}
function * test2() {
    yield * test1();
    //等效于
    // yield 'a';
    // yield 'b';
    yield 1;
    yield 2;
    yield 3;
}