TypeScript - 迭代器和生成器

你好啊,未来的编程超级巨星!欢迎来到TypeScript的精彩世界,我们将一起探索迭代器和生成器的神奇领域。如果这些术语现在对你来说听起来像是外星技术,别担心——在本教程结束时,你将能够像专业人士一样熟练地使用它们!那么,让我们卷起袖子,开始吧!

TypeScript - Iterators and Generators

迭代器

想象一下你有一个装满各种玩具的玩具箱。迭代器就像一根魔法棒,它可以帮助你一个接一个地穿过每个玩具,而不需要把整个箱子倒在地上。酷吧?让我们看看在TypeScript中这是如何工作的!

什么是迭代器?

迭代器是一个定义了next()方法的对象,该方法返回序列中的下一个项目。当没有更多项目时,它返回一个特殊值来指示序列已结束。

让我们创建我们的第一个迭代器:

function createNumberIterator() {
let n = 0;
return {
next: function() {
n += 1;
if (n <= 5) {
return { value: n, done: false };
}
return { value: undefined, done: true };
}
};
}

const numberIterator = createNumberIterator();
console.log(numberIterator.next()); // { value: 1, done: false }
console.log(numberIterator.next()); // { value: 2, done: false }
console.log(numberIterator.next()); // { value: 3, done: false }
console.log(numberIterator.next()); // { value: 4, done: false }
console.log(numberIterator.next()); // { value: 5, done: false }
console.log(numberIterator.next()); // { value: undefined, done: true }

在这个例子中,我们创建了一个从1数到5的迭代器。每次我们调用next()时,它都会给我们下一个数字。当它达到5时,通过返回{ value: undefined, done: true }来告诉我们它已经完成了。

使用迭代器和for...of循环

TypeScript使得使用迭代器和for...of循环更加容易。让我们看看如何操作:

function* numberGenerator() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}

for (const num of numberGenerator()) {
console.log(num);
}
// 输出:
// 1
// 2
// 3
// 4
// 5

这个for...of循环会自动使用迭代器来遍历所有值。就像有一个机器人助手为你从箱子里拿起每个玩具!

生成器

现在,让我们来谈谈生成器。如果迭代器是魔法棒,那么生成器就像是能够轻松创建这些魔法棒的巫师!

什么是生成器?

生成器是一种特殊的函数,可以被暂停和恢复,允许它随时间生成一系列值,而不是一次性计算并返回它们组成的数组。

让我们创建我们的第一个生成器:

function* countToFive() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}

const generator = countToFive();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3
console.log(generator.next().value); // 4
console.log(generator.next().value); // 5
console.log(generator.next().value); // undefined

在这个例子中,countToFive是一个生成器函数。yield关键字就像是在说:“这是下一个值,但让我们在这个之后休息一下。”每次我们调用next(),函数就会运行直到遇到yield,给我们那个值,然后暂停。

生成器和循环

当生成器与循环结合时,它们变得更加强大。让我们看一个例子:

function* evenNumbersUnder20() {
for (let i = 2; i < 20; i += 2) {
yield i;
}
}

for (const num of evenNumbersUnder20()) {
console.log(num);
}
// 输出:
// 2
// 4
// 6
// 8
// 10
// 12
// 14
// 16
// 18

这个生成器生成了所有小于20的偶数。就像有一个智能玩具分发器,只分发特定类型的玩具!

迭代器和生成器的区别

现在我们已经看到了迭代器和生成器的实际应用,让我们分解一下它们的关键区别:

特性 迭代器 生成器
定义 具有next()方法的对象 带有*符号的函数
状态管理 手动 自动
创建难度 更复杂 更简单
暂停/恢复 不是内置的 使用yield内置
内存效率 对于大型数据集可能更高效 对大型或无限序列极佳

迭代器就像是从零开始构建一个玩具机器人——你必须定义每一个小细节。另一方面,生成器就像得到一个预先构建好的机器人,你可以轻松定制。两者都有它们的位置和用途!

现实世界的例子

让我们用一个有趣的真实世界例子来结束我们的学习,它结合了我们所学的内容:

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

const fib = fibonacciGenerator();
for (let i = 0; i < 10; i++) {
console.log(fib.next().value);
}
// 输出:
// 0
// 1
// 1
// 2
// 3
// 5
// 8
// 13
// 21
// 34

这个生成器创建的是著名的斐波那契数列——一个每个数字都是前两个数字之和的数学数列。就像一个永无止境的楼梯,每个台阶都是由前两个台阶建造的!

就这样,我的编程学徒们!我们已经穿越了迭代器和生成器的领域,看到了它们的相似之处和不同之处,甚至创造了一些我们自己的魔法。记住,熟能生巧,所以不要害怕尝试这些概念。谁知道你会用你新的迭代器和生成器能力创造出多么惊人的程序呢?快乐编程,愿你的代码总是第一次编译就成功!

Credits: Image by storyset