「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
什么是生成器
生成器是ES6新增的一种函数控制的方案,它可以灵活地控制函数什么时候执行、什么时候暂停。 生成器函数也是一个函数,它和普通函数的区别:
(1)生成器函数需要在function后面加*
(2)生成器函数通过关键字yield来控制函数的执行与暂停
(3)生成器函数返回一个Generator(生成器)
生成器本质上是一个特殊的迭代器。
生成器函数
有以下代码可知,foo是个生成器函数,因为它符合生成器函数的条件: (1)function后面加* (2)使用yield来控制函数的执行与暂停 (3)当调用foo函数时,会返回一个生成器对象,它是一个特殊的迭代器,我们可以调用next方法。
function* foo() {
console.log('函数开始执行');
const value1 = 100
console.log('第一段代码:', value1);
yield
const value2 = 200
console.log('第二段代码:', value2);
yield
const value3 = 300
console.log('第三段代码:', value3);
yield
console.log('函数执行结束');
}
// 调用生成器函数时,会返回给我们一个生成器对象
const generator = foo()
// 开始执行第一段代码
generator.next()
// 开始执行第二段代码
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()
生成器函数的执行流程
当遇到yeild时暂停函数的执行,当遇到return时终止函数的执行。
function* foo() {
console.log('函数开始执行');
const value1 = 100
console.log('第一段代码:', value1);
yield value1
const value2 = 200
console.log('第二段代码:', value2);
yield value2
const value3 = 300
console.log('第三段代码:', value3);
yield value3
console.log('函数执行结束');
return '123'
}
const generator = foo()
console.log('返回值1:', generator.next());
console.log('返回值2:', generator.next());
console.log('返回值3:', generator.next());
console.log('返回值4:', generator.next());
生成器传递参数
通过yield我们让函数可以暂停分段执行。函数可以传递参数,那么我们如何给分段的函数传递参数呢?
我们在调用next时,可以给它传递参数,那么这个参数会作为上一个yield语句的返回值。
function* foo() {
console.log('函数开始执行');
const value1 = 100
console.log('第一段代码:', value1);
const n = yield value1
const value2 = 200 * n
console.log('第二段代码:', value2);
const count = yield value2
const value3 = 300 * count
console.log('第三段代码:', value3);
yield value3
console.log('函数执行结束');
return '123'
}
const generator = foo()
console.log(generator.next());
console.log(generator.next(10)); // 第二个next的参数作为第一个yield的返回值
console.log(generator.next(20));
那么我们想要给第一段传递参数呢?我们可以在函数调用的时候传递参数。
function* foo(num) {
console.log('函数开始执行');
const value1 = 100 * num
console.log('第一段代码:', value1);
const n = yield value1
const value2 = 200 * n
console.log('第二段代码:', value2);
const count = yield value2
const value3 = 300 * count
console.log('第三段代码:', value3);
yield value3
console.log('函数执行结束');
return '123'
}
const generator = foo(5)
console.log(generator.next());
console.log(generator.next(10));
console.log(generator.next(20));
生成器提前结束——return函数
我们可以使用return让生成器提前结束,之后再继续调用next不会继续生成值了。
function* foo(num) {
console.log('函数开始执行');
const value1 = 100 * num
console.log('第一段代码:', value1);
const n = yield value1
const value2 = 200 * n
console.log('第二段代码:', value2);
const count = yield value2
const value3 = 300 * count
console.log('第三段代码:', value3);
yield value3
console.log('函数执行结束');
return 123
}
const generator = foo(10)
console.log(generator.next());
console.log(generator.return(20));
生成器抛出异常——throw函数
我们可以在生成器内部捕获异常。
function* foo() {
console.log('代码开始执行');
const value1 = 100
try {
yield value1
} catch (error) {
console.log('捕捉到异常情况:', error);
yield 123
}
console.log('第二段代码继续执行');
const value2 = 200
yield value2
console.log('代码执行结束');
}
const generator = foo()
console.log(generator.next());
console.log(generator.throw('error message'));
console.log(generator.next());