Iterator 迭代器与 Generator 生成器
理解 JavaScript 迭代器协议和生成器函数的使用
问题
解释 Iterator 迭代器和 Generator 生成器的概念,以及它们的关系和使用场景。
解答
Iterator 迭代器
迭代器是一个对象,它实现了 next() 方法,每次调用返回 {value, done} 结构。
// 手动实现一个迭代器
function createIterator(arr) {
let index = 0;
return {
next() {
if (index < arr.length) {
return { value: arr[index++], done: false };
}
return { value: undefined, done: true };
}
};
}
const iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
可迭代对象
实现 [Symbol.iterator] 方法的对象可以被 for...of 遍历。
// 创建可迭代对象
const range = {
start: 1,
end: 5,
// 实现迭代器接口
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next() {
if (current <= end) {
return { value: current++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
// 可以使用 for...of
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
// 可以使用展开运算符
console.log([...range]); // [1, 2, 3, 4, 5]
Generator 生成器
生成器函数使用 function* 声明,通过 yield 暂停执行,自动实现迭代器协议。
// 生成器函数
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = numberGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
// 生成器天然可迭代
for (const num of numberGenerator()) {
console.log(num); // 1, 2, 3
}
用生成器简化可迭代对象
// 使用生成器重写 range
const range = {
start: 1,
end: 5,
*[Symbol.iterator]() {
for (let i = this.start; i <= this.end; i++) {
yield i;
}
}
};
console.log([...range]); // [1, 2, 3, 4, 5]
生成器的双向通信
function* conversation() {
const name = yield '你叫什么名字?';
const hobby = yield `${name},你的爱好是什么?`;
return `${name} 喜欢 ${hobby}`;
}
const talk = conversation();
console.log(talk.next().value); // '你叫什么名字?'
console.log(talk.next('小明').value); // '小明,你的爱好是什么?'
console.log(talk.next('编程').value); // '小明 喜欢 编程'
实际应用:异步流程控制
// 模拟异步操作
function fetchUser() {
return new Promise(resolve =>
setTimeout(() => resolve({ name: '张三' }), 100)
);
}
function fetchPosts(name) {
return new Promise(resolve =>
setTimeout(() => resolve([`${name}的文章1`, `${name}的文章2`]), 100)
);
}
// 生成器 + 执行器实现类似 async/await
function* fetchData() {
const user = yield fetchUser();
const posts = yield fetchPosts(user.name);
return posts;
}
// 简单的执行器
function run(generator) {
const gen = generator();
function step(value) {
const result = gen.next(value);
if (result.done) {
return Promise.resolve(result.value);
}
return Promise.resolve(result.value).then(step);
}
return step();
}
run(fetchData).then(posts => {
console.log(posts); // ['张三的文章1', '张三的文章2']
});
关键点
- 迭代器协议:实现
next()方法,返回{value, done}对象 - 可迭代协议:实现
[Symbol.iterator]方法,返回迭代器,支持for...of和展开运算符 - 生成器函数:
function*声明,yield暂停,自动实现迭代器协议 - 双向通信:
next(value)可以向生成器内部传值 - async/await 原理:生成器 + Promise 执行器是 async/await 的实现基础
目录