生成器是ES6中新增的一种函数控制、使用的方案,它可以让我们更加灵活的控制函数什么时候继续执行、暂停执 行等。
生成器函数也是一个函数,但是和普通的函数有一些区别:
①生成器函数需要在function的后面加一个符号:*
②生成器函数可以通过yield关键字来控制函数的执行流程:
③生成器函数的返回值是一个Generator(生成器):
不理解什么是迭代器可以看我上一篇文章关于迭代器的讲解;
// 当遇到yield时候值暂停函数的执行
// 当遇到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"
}
// generator本质上是一个特殊的iterator
const generator = foo()
console.log("返回值1:", generator.next())
console.log("返回值2:", generator.next())
console.log("返回值3:", generator.next())
console.log("返回值3:", generator.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"
}
// 生成器上的next方法可以传递参数
const generator = foo(5)
console.log(generator.next())
// // 第二段代码, 第二次调用next的时候执行的
console.log(generator.next(10))
console.log(generator.next(25))
运行结果:
return传值后这个生成器函数就会结束,之后调用next不会继续生成值了
后面调用也获取不到value值, done状态也会变成true;
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())
// 第二段代码的执行, 使用了return
// 那么就意味着相当于在第一段代码的后面加上return, 就会提前终端生成器函数代码继续执行
console.log(generator.return(15))
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
运行结果:
除了给生成器函数内部传递参数之外,也可以给生成器函数内部抛出异常:
function* foo() {
console.log("代码开始执行~")
const value1 = 100
try {
yield value1
} catch (error) {
console.log("捕获到异常情况:", error)
yield "abc"
}
console.log("第二段代码继续执行")
const value2 = 200
yield value2
console.log("代码执行结束~")
}
const generator = foo()
const result = generator.next()
generator.throw("error message")
运行结果:
我们发现生成器是一种特殊的迭代器,那么在某些情况下我们可以使用生成器来替代迭代器:
// 1.生成器来替代迭代器
function* createArrayIterator(arr) {
// 3.第三种写法 yield*
yield* arr
// 2.第二种写法
// for (const item of arr) {
// yield item
// }
// 1.第一种写法
// yield "abc" // { done: false, value: "abc" }
// yield "cba" // { done: false, value: "abc" }
// yield "nba" // { done: false, value: "abc" }
}
const names = ["abc", "cba", "nba"]
const namesIterator = createArrayIterator(names)
console.log(namesIterator.next())
console.log(namesIterator.next())
console.log(namesIterator.next())
console.log(namesIterator.next())
运行结果: