迭代器与生成器
约 693 字大约 2 分钟
2026-02-26
迭代器
迭代器就是对迭代过程的封装,它是一个对象,这个对象需要实现 next() 方法,每次调用 next() 会返回一个对象,这个对象需要包含 value 和 done 两个属性,其中 value 表示当前迭代的值,done 表示是否已经迭代完成
const arr = ['a', 'b', 'c']
let index = 0
const iterator = {
next() {
if (index < arr.length) {
return { value: arr[index++], done: false }
}
return { value: undefined, done: true }
},
}
console.log(iterator.next()) // { value: 'a', done: false }
console.log(iterator.next()) // { value: 'b', done: false }
console.log(iterator.next()) // { value: 'c', done: false }
console.log(iterator.next()) // { value: undefined, done: true }可迭代协议
ES6 规定,如果一个对象具有 Symbol.iterator 方法,并且该方法返回一个迭代器,则该对象就可被迭代器消费,该对象就是可迭代的
const arr = [1, 2, 3, 4]
const iterator = arr[Symbol.iterator]()
let res = iterator.next()
while (!res.done) {
console.log(res.value)
res = iterator.next()
}生成器
生成器函数允许定义一个非连续执行的函数作为迭代算法,生成器函数使用 function* 定义
最初调用时,生成器函数不执行任何代码,而是返回一个称为生成器的特殊迭代器,通过调用 next() 方法来消耗该生成器时,生成器函数执行,直到遇到 yield
function* gen() {
yield 'A'
yield 'B'
return 'C'
}
const it = gen() // 不执行任何代码
console.log(it.next()) // { value: 'A', done: false }
console.log(it.next()) // { value: 'B', done: false }
console.log(it.next()) // { value: 'C', done: true }相关信息
- 每个生成器只能迭代一次
- 生成器可以有返回值,其返回值为 done 为 true 时的 value 值
| API | 说明 |
|---|---|
throw(error) | 在当前暂停点向生成器内部抛出错误,并继续恢复执行;若内部未捕获,错误会继续向外抛出 |
return(value) | 在当前暂停点提前结束生成器,通常返回 { value, done: true } |
回传机制
yield 既能产出值,也能接收下一次 next 传入的值,参数会交给 yield 表达式的返回值
function* task() {
const a = yield 1
const b = yield a + 1
return b + 1
}
const it = task()
console.log(it.next()) // { value: 1, done: false }
console.log(it.next(10)) // { value: 11, done: false },a = 10
console.log(it.next(20)) // { value: 21, done: true },b = 20委托执行
yield* 会把当前生成器的迭代过程委托给另一个可迭代对象(最常见是另一个生成器),可以理解为把自身内容展开后交给另一个生成器
function* t1() {
yield 1
yield 2
}
function* t2() {
// yield t1() 错误写法只会产出一个 value 值为生成器对象的值
yield* t1()
yield 2
}
const it = t2()
console.log(it.next()) // { value: 1, done: false }
console.log(it.next()) // { value: 2, done: false }
console.log(it.next()) // { value: 2, done: false }
console.log(it.next()) // { value: undefined, done: true }