JavaScript 生成器与迭代器
生成器是可暂停的函数,迭代器是遍历数据的协议,两者配合实现惰性求值。
迭代器协议
迭代器需实现 next() 方法,返回 { value, done }:
JavaScript
function createIterator(arr) {
let index = 0;
return {
next() {
if (index < arr.length) {
return { value: arr[index++], done: false };
}
return { value: undefined, done: true };
}
};
}
const it = createIterator([1, 2, 3]);
it.next(); // { value: 1, done: false }
it.next(); // { value: 2, done: false }
it.next(); // { value: 3, done: false }
it.next(); // { value: undefined, done: true }
可迭代协议
对象需实现 [Symbol.iterator]() 方法,返回迭代器:
JavaScript
const iterable = {
data: [1, 2, 3],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return { value: this.data[index++], done: false };
}
return { done: true };
}
};
}
};
// 可用于 for...of
for (const item of iterable) {
console.log(item); // 1, 2, 3
}
生成器函数
使用 function* 定义,yield 暂停执行:
JavaScript
function* generator() {
yield 1;
yield 2;
yield 3;
}
const gen = generator();
gen.next(); // { value: 1, done: false }
gen.next(); // { value: 2, done: false }
gen.next(); // { value: 3, done: false }
gen.next(); // { value: undefined, done: true }
yield 表达式
yield 接收值
JavaScript
function* chat() {
const name = yield 'What is your name?';
return `Hello, ${name}!`;
}
const gen = chat();
gen.next(); // { value: 'What is your name?', done: false }
gen.next('Alice'); // { value: 'Hello, Alice!', done: true }
yield* 委托
JavaScript
function* gen1() {
yield 1;
yield 2;
}
function* gen2() {
yield* gen1();
yield 3;
}
[...gen2()]; // [1, 2, 3]
生成器实现异步
JavaScript
function* fetchUser() {
const user = yield fetch('/api/user');
const posts = yield fetch(`/api/posts/${user.id}`);
return posts;
}
// 执行器
function runGenerator(gen) {
const iterator = gen();
function handle(result) {
if (result.done) return result.value;
return result.value.then(data => handle(iterator.next(data)));
}
return handle(iterator.next());
}
实际应用
惰性序列
JavaScript
function* range(start, end, step = 1) {
for (let i = start; i < end; i += step) {
yield i;
}
}
[...range(0, 10, 2)]; // [0, 2, 4, 6, 8]
无限序列
JavaScript
function* fibonacci() {
let [a, b] = [0, 1];
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacci();
fib.next().value; // 0
fib.next().value; // 1
fib.next().value; // 1
fib.next().value; // 2
自定义迭代
JavaScript
class Tree {
constructor(value, left = null, right = null) {
this.value = value;
this.left = left;
this.right = right;
}
*[Symbol.iterator]() {
yield this.value;
if (this.left) yield* this.left;
if (this.right) yield* this.right;
}
}
const tree = new Tree(1,
new Tree(2),
new Tree(3)
);
[...tree]; // [1, 2, 3]
内置可迭代对象
| 对象 | 迭代方式 |
|---|---|
| Array | for...of, ... 展开 |
| String | 逐字符迭代 |
| Map | [key, value] 键值对 |
| Set | 元素值 |
| arguments | 函数参数 |
要点总结
- 迭代器实现
next()返回{ value, done } - 可迭代对象实现
[Symbol.iterator]方法 - 生成器
function*+yield实现惰性求值 yield*委托给其他生成器- 生成器可配合 Promise 实现异步流程控制
📝 发现内容有误?点击此处直接编辑