Generator 生成器是 ES6 中新增的一种函数控制、使用的方案,可以让开发人员更加灵活地控制函数什么时候暂停执行、什么时候继续执行等。
在此之前,函数的终止条件通常是返回值或者抛出异常。
生成器函数是一种特殊的函数:
- 生成器函数使用
function*
进行函数声明。ES6 没有规定,function 与函数名之间的星号,写在哪个位置。下面的写法都能通过,但一般是第三种。
function * foo(x, y) { ··· } function *foo(x, y) { ··· } function* foo(x, y) { ··· } function*foo(x, y) { ··· }
如果 Generator 函数是一个对象的属性,可以简写成下面的形式:
const obj = { * generatorMethod() {} } // 完整形式如下: const obj = { generatorMethod: function* () {} }
- 生成器函数内部可以通过 yield 语句来暂停函数的执行。
- 调用生成器函数,并不会执行生成器函数内部的代码,而是默认返回一个生成器对象。
生成器对象是内部实现的特殊的迭代器对象。
要想执行生成器函数内部的代码,需要调用生成器函数返回的生成器对象的function* fn() { console.log(1) } fn() // 会发现:fn 函数中的代码没有被执行。因为调用 fn() 只是会返回一个生成器
next()
方法。// 定义一个生成器函数 function* fn() { console.log(1) } // 调用生成器函数会返回一个生成器对象 const generator = fn() // 调用生成器对象的 next 方法才会执行生成器函数内部的代码 generator.next() // 执行生成器函数代码,打印 1
生成器函数的 yield 语句:
调用生成器函数返回的生成器对象的 next()
方法,会执行生成器函数内部的代码,直到遇到生成器函数内部的 yield 语句,就会暂停代码的执行。如果想要继续往后执行,需要再次调用生成器对象的 next()
方法。
// 定义一个生成器函数
function* fn() {
console.log(1)
yield
console.log(2)
}
// 调用生成器函数会返回一个生成器对象
const generator = fn()
// 调用生成器对象的 next 方法才会执行生成器函数内部的代码,直到遇到 yield 语句就会中断执行
generator.next() // 执行生成器函数代码,打印 1
// 要想继续执行,需要再次调用 next 方法
generator.next() // 继续执行生成器函数代码,打印 2
yield 语句后面可以跟一个表达式:
yield 语句后面可以跟一个表达式。
function* fn() {
console.log(1)
yield 50 + 50
console.log(2)
}
yield 语句的返回值:
yield 语句默认返回 undefined。
function* fn() {
console.log(1)
// yield 语句默认返回 undefined
const yield1Value = yield
console.log(2, yield1Value)
}
const generator = fn()
generator.next()
generator.next()
yield*
:
yield*
:可以看着是一种 yield 的语法糖。后面跟一个可迭代对象,会依次 yield 这个可迭代对象中的每个元素。
const names = ['Lee', 'Mary', 'Tom']
// 生成器函数返回一个生成器,是特殊的迭代器
function* generator() {
yield* names
// 相当于:
// yield names[0]
// yield names[1]
// yield names[2]
}
const namesGenerator = generator()
console.log(namesGenerator.next())
console.log(namesGenerator.next())
console.log(namesGenerator.next())
生成器对象的方法:
next()
方法:
next()
:用来执行生成器函数内部的代码,直到遇到 yield 或者 return 语句,就暂停代码的执行。
next()
方法的返回值:
调用生成器函数返回的生成器对象的 next()
方法,会返回一个包含 done 和 value 属性的对象。
- 如果是遇到 yield 暂停的,done 就为 false,value 为 yield 后面表达式的值。
- 如果是遇到 return 暂停的,done 就为 true,value 为 return 返回的值。
- 如果是函数执行完毕,done 就为 true,value 为 undefined(函数执行完毕默认返回 undefined,就相当于是遇到 return undefined,done 就为 true,value 为 undefined)。
function* fn() {
console.log(1)
yield
console.log(2)
}
const generator = fn()
console.log(generator.next()) // {value: undefined, done: false}
console.log(generator.next()) // {value: undefined, done: false}
function* fn() {
console.log(1)
yield 50 + 50
console.log(2)
}
const generator = fn()
console.log(generator.next()) // {value: 100, done: false}
console.log(generator.next()) // {value: undefined, done: false}
next()
方法的参数:
生成器函数返回的生成器对象的 next()
方法可以带一个参数,该参数会被当做上一个 yield 语句的返回值。
function* fn() {
console.log(1)
const yield1Value = yield
console.log(2, yield1Value)
}
const generator = fn()
generator.next()
generator.next('这是第二个 next 的参数,会作为第一个 yield 的返回值')
return()
方法:
return()
:用来直接结束生成器函数的执行。
function* fn() {
console.log(1)
yield
console.log(2, yield1)
}
const generator = fn()
// 执行到第一个 yield 后,就直接结束生成器函数的执行
generator.next()
generator.return()
throw()
方法:
throw()
:用来抛出异常并中断生成器函数的执行。
function* fn() {
console.log(1)
yield
console.log(2, yield1)
}
const generator = fn()
generator.next()
generator.throw(new Error('出错了'))