这是我参与更文挑战的第12天,活动详情查看:更文挑战
Generator生成器,也叫做生成器函数,它本质上是函数,但是它可以返回多次。Generator是ES6标准引入的新的数据类型。
概念
生成器是一个普通函数,特征在于:
- function关键字与函数名之间有一个星号(*),
function* - 函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
 - 函数体内部使用return,可以返回给定的值,并且终结遍历Generator函数。
 
function* foo(x) {
    yield x + 1;
    yield x + 2;
    return x + 3;
    yield x + 4;
}
复制代码
生成器函数与普通函数对比:
- 都是通过括号()执行。
 - 调用生成器函数后,函数并不立即执行,返回的不是函数运行结果,而是一个迭代器对象。
 - 通过迭代器对象
next方法分段执行函数,获取函数内部yield产出值。 
const r = foo(0);
r.next();
// { value: 1, done: false }
r.next();
// { value: 2, done: false }
r.next();
// { value: 3, done: true }
r.next();
// { value: undefined, done: true } 被return终结了
r.next();
// { value: undefined, done: true }
复制代码
yield表达式
yield只能用在生成器函数中,在普通函数或者其它地方使用都会报语法错误。
yield在生成器内部表示暂停标志,对调用的地方来说表示产出值。
yield表达式与return语句既有相似之处,也有区别。
- 相似之处在于,都能返回紧跟在语句后面的那个表达式的值。
 - 区别在于每次遇到
yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。 - 一个函数里面,只能执行一次(或者说一个)
return语句,但是可以执行多次(或者说多个)yield表达式。 - 正常函数只能返回一个值,因为只能执行一次
return;Generator函数可以返回一系列的值,因为可以有任意多个yield。 
next方法
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
Generator函数从暂停状态到恢复运行,它的上下文状态(context)是不变的。通过next方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。也就是说,可以在Generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。
function* dataConsumer () {
  console.log('Started');
  console.log(`1. ${yield}`);
  console.log(`2. ${yield}`);
  return 'result';
}
// 等效代码
function* dataConsumer () {
  console.log('Started');
  let result = yield;
  console.log(`1. ${result}`);
  result = yield;
  console.log(`2. ${result}`);
  return 'result';
}
let genObj = dataConsumer();
genObj.next(); // {value: undefined, done: false}
// Started
genObj.next('a'); // {value: undefined, done: false}
// 1. a
genObj.next('b'); // {value: "result", done: false}
// 2. b
复制代码
for…of循环
for...of循环可以自动遍历 Generator函数运行时生成的Iterator对象,且此时不再需要调用next方法。
function* foo () {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
  return 6;
}
for (const v of foo()) {
  console.log(v);
}
复制代码
注意,一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for...of循环之中。
但是yield 5之后的代码是会被执行。
异常
Generator函数返回的遍历器对象都有一个throw方法,可以在函数体外抛出错误,然后在Generator函数体内捕获。
const g = function* () {
    try {
        yield;
    } catch(e){
        console.log('内部捕获', e);// 捕获i对象的第一个throw
    }
};
const  i = g();
i.next();
try {
    i.throw('a');// 在函数体外抛出错误,在函数体内捕获错误
    i.throw('b');// 在函数体外抛出错误,在函数体外捕获错误
} catch (e) {
    console.log('外部捕获', e);
}
// 结果
// 内部捕获 a
// 外部捕获 b
复制代码
                    © 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
    

















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)