生成器(generator)
- 生成器(generator)
- generator
- 生成器:由构造函数Generator创建的对象,该对象既是一个迭代器,同时又是一个可迭代对象(满足可迭代协议的对象)
- 生成器函数的特点:
-
调用生成器函数,会返回一个生成器,而不是执行函数体(因为,生成器函数的函数体执行,受到生成器控制)
-
每当调用了生成器的next方法,生成器的函数体会从上一次yield的位置(或者开始位置)运行到下一个yield
- yield关键字只能在生成器内部使用,不可以在普通函数内部使用。
- yield表示暂停,并返回一个当前迭代的数据。
- 如果没有下一个yield,到了函数底部,这时done的值设为true。
-
yield关键字后面的表达式返回的数据,会作为当前迭代的数据
-
生成器函数返回的值,会作为迭代结束时的value,但是,如果在迭代结束后,反复调用next函数,这时value的值为undefined。
-
生成器调用next的时候,可以传递参数,该参数会作为生成器函数体上一次yield表达式的值。
-生成器函数第一次传参数没有任何意义 -
生成器带有一个throw方法,该方法于next的效果相同,唯一的区别在于
-next方法传递的参数会被返回一个正常值
-throw方法传递的参数是一个错误,会导致生成器函数内部发生一个错误
function* G2() {
console.log("运行G2 - 开始")
let result = yield "g1"
console.log("运行G2 - 第一次")
result = yield "g2"
console.log("运行G2 - 第二次")
return "g3"
}
function* createGenerator() {
console.log("运行生成器 - 开始")
let result = yield 1;//将1作为第一次迭代的值, result的值可以通过next方法的参数来改变,不传的话result的值为undefined
console.log("运行生成器 - 第一次", result)
result = yield 2;//将2作为第二次迭代的值
console.log("运行生成器 - 第二次", result)
result = yield* G2();//如果加入*号调用则进入新的生成器内部执行
console.log("运行内部生成器 - 结束", result)
result = yield 3;
console.log("运行生成器 - 第三次", result)
result = yield 4;
console.log("结束", result)
}
const generator = createGenerator();//调用后一定得到一个生成器
generator.next();
generator.next(new Error("代码错误"));
generator.next();
结果:
运行生成器 - 开始
运行生成器 - 第一次 Error: 代码错误
at test.html:36
运行生成器 - 第二次 undefined
运行G2 - 开始
const generator = createGenerator();//调用后一定得到一个生成器
generator.throw(new Error("代码错误"));
generator.next();
generator.next();
结果:
Uncaught Error: 代码错误
at test.html:35
7. 生成器带有一个return方法,该方法会直接结束生成器函数
function* G2() {
console.log("运行G2 - 开始")
let result = yield "g1"
console.log("运行G2 - 第一次")
result = yield "g2"
console.log("运行G2 - 第二次")
return "g3"
}
function* createGenerator() {
console.log("运行生成器 - 开始")
let result = yield 1;//将1作为第一次迭代的值, result的值可以通过next方法的参数来改变,不传的话result的值为undefined
console.log("运行生成器 - 第一次", result)
result = yield 2;//将2作为第二次迭代的值
console.log("运行生成器 - 第二次", result)
result = yield* G2();//如果加入*号调用则进入新的生成器内部执行
console.log("运行内部生成器 - 结束", result)
result = yield 3;
console.log("运行生成器 - 第三次", result)
result = yield 4;
console.log("结束", result)
}
const generator = createGenerator();//调用后一定得到一个生成器
generator.next();
generator.next();
generator.return("aaaa");
generator.next("aaaa");
结果:
运行生成器 - 开始
运行生成器 - 第一次 undefined
function* createGenerator() {
console.log("运行生成器 - 开始" )
let result = yield 1;//将1作为第一次迭代的值, result的值可以通过next方法的参数来改变,不传的话result的值为undefined
console.log("运行生成器 - 第一次", result)
result = yield 2;//将2作为第二次迭代的值
console.log("运行生成器 - 第二次", result)
result = yield 3;
console.log("运行生成器 - 第三次", result)
result = yield 4;
console.log("结束", result)
}
const generator = createGenerator();//调用后一定得到一个生成器
console.log(generator.next())
console.log(generator.next("a"))
console.log(generator.next("b"))
console.log(generator.next("c"))
console.log(generator.next("d"))
//结果
运行生成器 - 开始
{value: 1, done: false}
运行生成器 - 第一次 a
{value: 2, done: false}
运行生成器 - 第二次 b
{value: 3, done: false}
运行生成器 - 第三次 c
{value: 4, done: false}
结束 d
{value: undefined, done: true}
- 若需要在生成器内部调用其他生成器,注意:如果直接调用,得到的是一个生成器,如果加入*号调用则进入新的生成器内部执行,如果是yield *生成器函数()调用生成器函数,则该函数的返回结果,为该表达式的结果
function* G2() {
console.log("运行G2 - 开始")
let result = yield "g1"
console.log("运行G2 - 第一次")
result = yield "g2"
console.log("运行G2 - 第二次")
return "g3"
}
function* createGenerator() {
console.log("运行生成器 - 开始")
let result = yield 1;//将1作为第一次迭代的值, result的值可以通过next方法的参数来改变,不传的话result的值为undefined
console.log("运行生成器 - 第一次", result)
result = yield 2;//将2作为第二次迭代的值
console.log("运行生成器 - 第二次", result)
result = yield* G2();//如果加入*号调用则进入新的生成器内部执行
console.log("运行内部生成器 - 结束", result)
result = yield 3;
console.log("运行生成器 - 第三次", result)
result = yield 4;
console.log("结束", result)
}
const generator = createGenerator();//调用后一定得到一个生成器
for(let item of generator){
console.log(item)
}
运行结果:
运行生成器 - 开始
1
运行生成器 - 第一次 undefined
2
运行生成器 - 第二次 undefined
运行G2 - 开始
g1
运行G2 - 第一次
g2
运行G2 - 第二次
运行内部生成器 - 结束 g3
3
运行生成器 - 第三次 undefined
4
结束 undefined