应用场景
简化迭代器的编写。
什么是生成器?
是一个通过构造函数Generator创建的对象。生成器既是一个迭代器,又是一个可迭代对象。
如何创建生成器?
生成器的创建,必须使用生成器函数(Generator Function)
// 这是一个生成器函数,该函数一定返回一个生成器
function *method(){
}
这是得到生成器的唯一途径。
举例:
function *method(){
}
const generator = method();
console.log(generator)
有next方法,又有知名符号,说明这是一个迭代器,所以:
- 能调用.next()方法;
- 能用for-of循环
生成器函数内部是如何执行的?
生成器函数内部是为了给生成器的每次迭代提供数据的。
先看一个例子:
function *test(){
console.log('a')
}
const generator = test();
// 没有输出a,因为test函数并没有执行
由此, 我们要消除一个误解:
生成器函数(上例中的test)内部并不执行,调用函数只是用来创建生成器(上例中的generator)。
那么,生成器函数内部到底是如何运行的?
生成器函数内部是为了给生成器的每次迭代提供数据的。
分析:
-
得到生成器是为了迭代(不断拿到下一个数据)
-
函数里面是给生成器每一次迭代提供数据的
const generator = test(); // 该生成器没有迭代 // 生成器调用next()才叫迭代;不调用不叫迭代,所以迭代函数没有运行 -
那么生成器函数里面是如何提供数据
- 每次调用生成器的next方法,将导致生成器函数运行到下一个yield关键字位置。
- yield是一个关键字,该关键字只能在生成器函数内部使用,表达‘产生’一个迭代数据的意思
举例说明:
function *test(){ console.log('第一次运行'); yield 1; console.log('第二次运行'); yield 2; console.log('第三次运行'); } const generator = test(); console.log(generator.next());分析: 1. generator本身不执行,调用next方法才执行 2. 第一次调用next方法,得到:value是yield的值;函数还没运行完,所以done为false,当函数运行完done为true
- 继续调用next方法,得到:
练习:编写一个生成器
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [6, 7, 8, 9];
function *createIterator(arr){
for(const item of arr){
yield item;
}
}
const iter1 = createIterator(arr1);
const iter2 = createIterator(arr2);
有哪些需要注意的细节?
-
生成器可以有返回值,返回值出现在第一次done为true的value属性中;
-
调用生成器next方法时,可以传递参数,传递的参数会交给yield表达式的返回值
举例说明:
function *test(){ let info = yield 1; console.log(info); info = yield 2 + info; console.log(info); } const generator = test();分析:
- 第一次调用next卡在yield1;
- 此时调用next方法,传递一个参数:5;
- 此时info为5;
- 此时yield为7,又卡在了yield;
- 继续调用next,但是不传参数;
- 此时info为undefined
-
第一次调用next方法时,传参没有任何意义;
-
在生成器内部,可以调用其他生成器函数,但是要注意加上*号
生成器的其他API
- return方法:调用该方法,可以提前结束生成器函数,从而提前让整个迭代过程结束;
- throw方法:调用该方法,可以在生成器中产生一个错误。