Skip to content
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

迭代器与生成器

可迭代对象

如果一个对象具有 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

当目标为兼容 ES5 的引擎时,迭代器仅允许用于 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 循环,以针对引擎内置的迭代器实现。