TypechoJoeTheme

至尊技术网

登录
用户名
密码

JavaScript生成器函数与迭代器详解

2025-11-12
/
0 评论
/
32 阅读
/
正在检测是否收录...
11/12

在现代JavaScript开发中,异步编程和数据流处理变得越来越重要。为了更优雅地管理复杂的控制流程,ES6引入了两个强大的语言特性:生成器函数(Generator Functions)迭代器(Iterators)。它们不仅为开发者提供了更灵活的数据遍历方式,还为异步操作的同步化书写奠定了基础。

什么是迭代器?

在JavaScript中,迭代器是一个符合迭代器协议的对象,即它拥有一个 next() 方法,该方法返回一个形如 { value: any, done: boolean } 的对象。其中 value 表示当前迭代的值,done 是一个布尔值,表示是否已经遍历完成。

原生支持迭代器的数据结构包括数组、字符串、Map、Set等。这些对象之所以能被 for...of 循环遍历,是因为它们实现了 可迭代协议 —— 即拥有一个以 Symbol.iterator 为键的方法。

javascript
const arr = [1, 2, 3];
const iterator = arrSymbol.iterator;

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 }

通过手动调用 next(),我们可以逐步获取每一个值。这种“惰性求值”的机制使得处理大量数据或无限序列成为可能。

生成器函数:一种特殊的函数

生成器函数是定义迭代器的简便方式。它使用 function* 语法声明,并通过 yield 关键字暂停和恢复执行。

javascript
function* countUp() {
yield 1;
yield 2;
yield 3;
}

const gen = countUp();
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 }

每次调用 next(),函数会从上次 yield 暂停的地方继续执行,直到遇到下一个 yield 或函数结束。这使得生成器可以按需产生值,避免一次性计算所有结果。

yield 与 return 的区别

yield 不仅可以返回值,还能接收外部传入的值。当 next(value) 被调用时,传入的参数会作为当前 yield 表达式的返回值。

javascript
function* echo() {
const input = yield "ready";
yield You said: ${input};
}

const g = echo();
console.log(g.next().value); // "ready"
console.log(g.next("Hello").value); // "You said: Hello"

return 会终结生成器,使后续调用 next() 都返回 { done: true }

实际应用场景

生成器非常适合处理无限序列或大数据流。例如,实现一个斐波那契数列生成器:

javascript
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}

const fib = fibonacci();
for (let i = 0; i < 10; i++) {
console.log(fib.next().value);
}

这段代码不会导致内存溢出,因为数值是按需生成的。

此外,生成器曾被广泛用于异步流程控制(如 co 库),虽然现在已被 async/await 取代,但其思想依然影响深远。async 函数本质上是返回 Promise 的生成器的语法糖。

自定义可迭代对象

结合生成器和 Symbol.iterator,我们可以轻松创建自定义可迭代类型:

javascript
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}

*Symbol.iterator {
for (let i = this.start; i <= this.end; i++) {
yield i;
}
}
}

for (const n of new Range(1, 5)) {
console.log(n); // 1, 2, 3, 4, 5
}

这种方式让我们的类也能被 for...of、扩展运算符等语法自然支持。

总结

JavaScript迭代器生成器函数可迭代对象yieldGeneratorfor...of
朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/38406/(转载时请注明本文出处及文章链接)

评论 (0)