迭代器和生成器

可迭代对象

如果一个对象实现了 Symbol.iterator 属性,则该对象被认为是可迭代的。一些内置类型,如 ArrayMapSetStringInt32ArrayUint32Array 等,已经实现了 Symbol.iterator 属性。对象上的 Symbol.iterator 函数负责返回要迭代的值列表。

Iterable 接口

如果我们想使用上面列出的可迭代类型,Iterable 是一个我们可以使用的类型。以下是一个示例

ts
function toArray<X>(xs: Iterable<X>): X[] {
return [...xs]
}

for..of 语句

for..of 循环遍历一个可迭代对象,在对象上调用 Symbol.iterator 属性。以下是一个在数组上使用 for..of 循环的简单示例

ts
let someArray = [1, "string", false];
for (let entry of someArray) {
console.log(entry); // 1, "string", false
}

for..offor..in 语句

for..offor..in 语句都用于迭代列表;但迭代的值不同,for..in 返回正在迭代的对象的列表,而 for..of 返回正在迭代的对象的数字属性的列表。

以下是一个演示这种区别的示例

ts
let list = [4, 5, 6];
for (let i in list) {
console.log(i); // "0", "1", "2",
}
for (let i of list) {
console.log(i); // 4, 5, 6
}

另一个区别是,for..in 可以操作任何对象;它可以用来检查对象上的属性。另一方面,for..of 主要关注可迭代对象的**值**。内置对象,如 MapSet,实现了 Symbol.iterator 属性,允许访问存储的值。

ts
let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";
for (let pet in pets) {
console.log(pet); // "species"
}
for (let pet of pets) {
console.log(pet); // "Cat", "Dog", "Hamster"
}

代码生成

针对 ES5 和 ES3

当目标是 ES5 或 ES3 兼容的引擎时,迭代器只允许在 Array 类型的**值**上使用。在非数组值上使用 for..of 循环是错误的,即使这些非数组值实现了 Symbol.iterator 属性。

编译器将为 for..of 循环生成一个简单的 for 循环,例如

ts
let numbers = [1, 2, 3];
for (let num of numbers) {
console.log(num);
}

将被生成为

js
var numbers = [1, 2, 3];
for (var _i = 0; _i < numbers.length; _i++) {
var num = numbers[_i];
console.log(num);
}

针对 ECMAScript 2015 及更高版本

当目标是 ECMAScript 2015 兼容的引擎时,编译器将生成 for..of 循环来针对引擎中的内置迭代器实现。

TypeScript 文档是一个开源项目。欢迎您通过 发送 Pull Request ❤ 来帮助我们改进这些页面。

贡献者
MHMohamed Hegazy (57)
OTOrta Therox (15)
GBGabriel Burdeti (3)
NSNick Schonning (1)
JYJason Yu (1)
11+

上次更新时间:2024 年 3 月 21 日