迭代器协议与生成器函数
迭代器协议与生成器函数
for...of 背后的协议
能被 for...of 遍历的对象(数组、字符串、Map、Set)都实现了 可迭代协议(Iterable):对象有一个 Symbol.iterator 方法,调用后返回一个迭代器(Iterator)——带 next() 方法的对象:
const arr = ['a', 'b']
const it = arr[Symbol.iterator]()
it.next() // { value: 'a', done: false }
it.next() // { value: 'b', done: false }
it.next() // { value: undefined, done: true }
每次 next() 返回 { value, done },done 为 true 表示遍历结束。展开运算符 ...、解构、Promise.all 之外,new Map()、Array.from 都基于这套协议。
手写一个可迭代对象
const range = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from
return {
next: () => current <= this.to
? { value: current++, done: false }
: { value: undefined, done: true },
}
},
}
console.log([...range]) // [1, 2, 3]
生成器 generator:语法糖利器
手写迭代器很繁琐,function* 生成器会自动返回迭代器,yield 暂停并返回值:
function* rangeGen(from, to) {
for (let i = from; i <= to; i++) {
yield i // 每次 next 执行到这里暂停,状态被完整保留
}
}
const it2 = rangeGen(1, 3)
it2.next() // { value: 1, done: false }
生成器天然可迭代,直接用在 for...of 里。还可以双向传值——next(arg) 的参数会成为上一个 yield 的返回值:
function* quiz() {
const answer = yield '2 + 2 = ?'
yield answer === 4 ? '正确' : '错误'
}
const q = quiz()
q.next() // { value: '2 + 2 = ?' }
q.next(4) // { value: '正确' }
实际用途
- 自定义数据结构支持遍历(链表、树的遍历器)
- 惰性序列:生成无限数列但只在需要时求值
- 经典的 redux-saga 用 generator 编排异步副作用
async function*异步生成器 +for await...of:Node 流和分页拉取的优雅写法(如游标翻页 API)
迭代器协议是 ES6 为"如何消费集合"定下的统一接口,理解后看各种语言特性会有串起来的感觉。
看到这里了?如果这篇文章帮到过你
请我喝瓶可乐就好 🥤

评论0 条
还没有评论,来抢沙发~