我们知道 函数是从上到下执行的,但 ES6 在2016年6月发布时,这一切都改变了,它带来了在执行过程中暂停函数的能力,又能从暂停处继续执行。
这是怎么做到的呢? 也称为生成器函数。
官方的介绍生成器函数提供了一个强大的选择,它允许你定义一个包含自有迭代算法的函数, 同时它可以自动维护自己的状态。 生成器函数使用 * 语法编写。 最初调用时,生成器函数不执行任何代码,而是返回一种称为 的迭代器。 通过调用生成器的下一个方法消耗值时, 函数将执行,直到遇到 yield 关键字。
生成器函数可以在中间暂停一次或多次生成器和迭代器的区别,之后可以重新恢复。当标准函数被调用时,控制将由被调用函数控制,直到它返回为止,但是生成器函数允许调用函数控制被调用函数的执行。如下图示意:
生成器函数关键的三个概念:
下面来看一个基本的实例。
创建生成器函数
中的生成器函数的创建与其他函数非常相似,除了语法上的一点差异,如下:
function* citySolitaire() {
yield "北京市";
yield "上海市";
yield "深圳市";
yield "广州市";
yield "天津市";
}
区别在于函数定义本身,生成器函数是使用 * 语法声明的。
yield 关键字
当一个生成器函数被调用时,它会一直执行直到遇到一个 yield 表达式。此时,生成器函数暂停,返回 yield 关键字后定义的值,等待继续执行,直到再次调用该函数。
返回值
中生成器函数和常规函数之间的另一个区别:生成器函数在封装的对象中返回其值。从技术上讲,生成器符合迭代器协议(如 Maps 和 ),这意味着封装的对象看起来像这样:
{
value, // 从生成器函数获取的下一个值
done; // 一个标志,标记是否是序列中的最后一个值
}
如前面定义的生成器函数 ,从中获取其值,如下:
const city = citySolitaire();
console.log(city.next()); // { value: '北京市', done: false }
每次调用 next() 方法时生成器和迭代器的区别,都会以前面提到的格式返回一个对象。要获取数据,只需访问 value 属性。当 done 属性的值为 false 时,就意味着还有更多的数据需要检索,可以再次调用生成器。如下:
const city = citySolitaire();
console.log(city.next()); // { value: '北京市', done: false }
console.log(city.next()); // { value: '上海市', done: false }
console.log(city.next()); // { value: '深圳市', done: false }
console.log(city.next()); // { value: '广州市', done: false }
console.log(city.next()); // { value: '天津市', done: false }
console.log(city.next()); // { value: undefined, done: true }
正如上面执行的结果,当执行到最后一个的时候再次执行 next() ,就会返回期望的 done 为 true 。