生成器的学习
什么是生成器
生成器是ES6新增的一种函数控制、使用的方法,可以更加灵活的龙之函数什么时候继续执行、暂停执行等。
生成器也是一个函数,但是和普通函数有一些区别:
-
生成器函数需要在function的后面加一个符号:*
-
生成器函数可以通过yield关键字来控制函数额执行流程
-
生成器函数的返回值是一个Generator:
- 生成器实际上是一种特殊的迭代器
-
我们可以在调用next函数的时候给它传递参数,那么这个参数会作为上一个yield语句的返回值;
- 也就是说我们为本次函数代码块执行提供了一个值
生成器函数执行:
function* foo(initial) {
console.log("函数开始执行~")
const result = yield initial
console.log(result)//aaa
const result2 = yield result
console.log(result2)//bbb
console.log("结尾~")
}
//返回生成器
const generator = foo("mjy")//没有任何打印
//执行到第一个yield,并且暂停 第一个数据一般通过函数的参数方式传参
console.log(generator.next())//{ value: 100, done: false }
//执行到第二个yield,并且暂停
console.log(generator.next("aaa"))//{ value: 200, done: false }
// //执行剩余代码
console.log(generator.next("bbb"))//{ value: undefined,, done: false }
生成器可以使用return函数传值,传之后这个生成器函数就会结束,之后调用next不会继续生成值了,同时上一个yield到这个yield之间的函数内代码也不会再执行了.
function* foo(initial) {
console.log("函数开始执行~")
const result = yield initial
console.log(result)//aaa
const result2 = yield result
console.log(result2)//未执行代码
console.log("结尾~")
}
//返回生成器
const generator = foo("mjy")//没有任何打印
//执行到第一个yield,并且暂停 第一个数据一般通过函数的参数方式传参
console.log(generator.next())//{ value: 100, done: false }
//执行到第二个yield,直接终止到这个生成器
console.log(generator.return("aaa"))//{ value: 200, done: false }
// //执行剩余代码
console.log(generator.next("bbb"))//{ value: undefined,, done: false }
/* 代码执行结果
函数开始执行~
{ value: 'mjy', done: false }
{ value: 'aaa', done: true }
{ value: undefined, done: true }
*/
生成器抛出异常
除了给生成器函数内部传递参数之外,也可以给生成器函数内部抛出异常:
抛出异常后我们可以在生成器函数中捕获异常;
catch语句中不能继续yield新的值了,但是可以再catch语句外使用yield继续中断函数的执行;
function* foo() {
console.log("函数开始执行~")
try {
yield "mjy"
} catch (err){
console.log("内部捕获异常:",err)
}
yield 222
console.log("函数执行结束~")
}
const generator = foo()
const result = generator.next() //函数开始执行~
generator.throw("error message")// console.log("内部捕获异常:",err)
console.log(generator.next())//函数执行结束~
// { value: undefined, done: true }
/*函数运行结果
函数开始执行~
内部捕获异常: error message
函数执行结束~
{ value: undefined, done: true }
*/
生成器替代迭代器
生成器是一种特殊的迭代器,那么在一些情况下我们可以使用生成器来替代迭代器
function *creatArrayIterator(arr){
for (const item of arr){
yield item
}
}
const names = ["1","2","3","4","5"]
nameIterator = creatArrayIterator(names)
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
/*
{ value: '1', done: false }
{ value: '2', done: false }
{ value: '3', done: false }
{ value: '4', done: false }
{ value: '5', done: false }
{ value: undefined, done: true }
*/
可以使用yield*lai生产一个可迭代对象:
相当于是yield的语法糖,会依次迭代这个可迭代对象
function *creatArrayIterator(arr){
yield* arr
}
const names = ["1","2","3","4","5"]
nameIterator = creatArrayIterator(names)
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
/*
{ value: '1', done: false }
{ value: '2', done: false }
{ value: '3', done: false }
{ value: '4', done: false }
{ value: '5', done: false }
{ value: undefined, done: true }
*/
自定义类迭代-生成器实现
之前迭代器中的代码我们也可以使用yield* 换成生成器
生成器是一个迭代器,那么我们我们可以将对这个生成器对象放在任何需要传入可迭代对象的地方例如for...of 创建Set Pomise.all中传参