生成器(generator)函数能生成一组值的序列,每个值的生成是基于每次请求,并不是立即生成,必须由我们显示的向生成器请求一个新的值。在结束之前,每当生成器生成一个值后不会停止执行,而是挂起等待下一次请求。
// 生成器函数,在function后面添加*
function* TestGenerator() {
yield 'xingjieStart'
yield* OtherGenerator() // 一个生成器将执行权交给另一个生成器 yield后面加*
yield* NoYieldGenerator() // 内部没有yield不会生成值,
yield defaultFunction() // 普通函数返回函数执行结果
yield 'xingjieEnd'
}
function* OtherGenerator() {
yield 'otherStart'
yield 'otherEnd'
}
function* NoYieldGenerator() {
return 'have no yield'
}
function defaultFunction() {
return 'this is defaultFunction'
}
// 迭代器
const testGenerator = TestGenerator()
const testGenerator2 = TestGenerator()
// 调用迭代器的next方法请求一个新的值
const result1 = testGenerator.next()
console.log('result1 : ', result1)
// 2个迭代器之间互不干扰(类似构造函数)
const _result1 = testGenerator2 .next()
console.log('_result1 : ', _result1 )
// for-of 用来遍历迭代器,在完成前会自动next
for(let item of testGenerator) {
console.log('item: ', item)
}
/** logs
result1 : {value: "xingjieStart", done: false}
_result1: {value: "xingjieStart", done: false}
item: otherStart
item: otherEnd
item: this is defaultFunction
item: xingjieEnd
*/
for-of 语法糖
while(!(item = TestGenerator().next()).done) {
console.log('item: ', item.value)
}
使用生成器生成ID
function* IdGenerator() {
let id = 0
while(true) {
yield ++id
}
}
const idGenerator = IdGenerator()
for(let i = 0; i < 10; i++) {
console.log('id: ', idGenerator.next().value)
}
与生成器交互
// 向生成器发送数据
function* TestGenerator() {
let first = yield '---a----' // 生成一个值'---a---'的同时会返回一个中间计算结果,通过带参数调用迭代器将参数传回迭代器
let second = yield first + '----b----'
yield first + '----c----' + second
}
const testGenerator = TestGenerator()
console.log(testGenerator .next().value) // "---a----"
console.log(testGenerator .next('xj').value) // "xj----b----"
console.log(testGenerator .next('帅').value) // "xj----c----帅"
// 生成器本身也可以带参数
function* TestGenerator2(act) {
let first = yield act + '---a----'
let second = yield act + first + '----b----'
yield act + first + '----c----' + second
}
const testGenerator2 = TestGenerator2('大喊:')
const _testGenerator2 = TestGenerator2('破音:')
console.log(testGenerator2 .next().value) // "大喊: ---a----"
console.log(_testGenerator2 .next().value) // "破音: ---a----"
console.log(testGenerator2 .next('xj').value) // "大喊: xj----b----"
console.log(_testGenerator2 .next('xj').value) // "破音: xj----b----"
console.log(testGenerator2 .next('帅').value) // "大喊: xj----c----帅"
console.log(_testGenerator2 .next('帅').value) // "破音: xj----c----帅"
生成器双向通信:yield从生成器返回值,迭代器的next()方法传入值。
如果没有等待中的yield表达式,则无法传入值,所以第一次调用迭代器的next()方法时如果需要传入值,可以在调用生成器自身时传入参数:TestGenerator2('大喊:')
- 所有迭代器还有throw方法,可以抛出一个异常