让前端飞程序员Web 前端开发

生成器 Generator

2018-07-31  本文已影响0人  你的肖同学

在新的 ES 标准中,生成器(Generator) 几乎是一个完全崭新的函数类型,它能生成一组值得序列,但每个值的生成是基于每次请求,并不同于标准函数那样立即生成。

这样特殊的性质,也使得它成为了我们解决 JS 异步编程的一个利器。

生成器的遍历

要遍历生成器很简单,只需要用for...of函数就可以取出每一步从生成器中返回的值。举个例子:

function* AnimalGenerator() {
    yield 'dog';
    yield 'cat';
    yield 'fish';
}

for(let animal of AnimalGenerator()) {
    console.log(animal);
}
// => dog cat fish

生成器嵌套

生成器嵌套的方式,可以将一个生成器委托给另外一个生成器,在执行到某个节点的时候,返回该生成器中的值:

function* AllGenerator() {
    yield 'human';
    yield* AnimalGenerator();
    yield 'AI';
}

for(let item of AllGenerator()) {
    console.log(item);
}
// => human dog cat fish AI

迭代器

在调用生成器之后,会创建一个 迭代器(Iterator) 并返回出来,而利用迭代器就可以逐步返回生成器中的值:

const animalIterator = AnimalGenerator();

const animal1 = animalIterator.next();
const animal2 = animalIterator.next();
const animal3 = animalIterator.next();
const animal4 = animalIterator.next();

console.log(animal1, animal2, animal3, animal4);
// => {value: "dog", done: false} {value: "cat", done: false} {value: "fish", done: false} {value: undefined, done: true}

在每次执行迭代器next方法的时候,返回一个对象,对象包含两个属性:

除此之外,迭代器的next还可以接收一个参数作为上一次yield的返回值:

function* Next(x) {
    const y = 3 * yield (x + 1);
    const z = yield (y / 10);
    yield (x + y + z);
}

const next = Next(1);

const result1 = next(); 
// => value: 2
const result2 = next(10); 
// => value: 3
const result3 = next(12); 
// => value: 43

这结果看起来有点绕,但是捋一捋就会发现很有意思:

生命周期

看了这些生成器的基本用法,肯定会对它的内部原理很好奇。概括一下,就是直接调用一个生成器不会直接执行,而是会创建一个新的迭代器返回出来,通过迭代器我们才能对其进行求值。生成器每生成一个值都会自己挂起执行,然后等待下一个请求。

在某种当面来说,生成器的工作更像是一个在状态中运动的状态机。

生成器生命周期

如上图所示,生成器的生命周期主要分为四个阶段:

从生命周期我们可以看到,在整个周期里,只要我们取得生成器的控制权,它的执行上下文就会一直保存,而不会想标准函数一样退出后就销毁。

上一篇下一篇

猜你喜欢

热点阅读