# 迭代器和生成器

# 可迭代的

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

# Iterable 接口

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

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

# for..of 语句

for..of循环遍历一个可迭代对象,调用该对象的 Symbol.iterator属性。这是一个数组上的简单 for..of循环:

let someArray = [1, "string", false];

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

# for..of 与 for..in 语句

for..offor..in语句都遍历列表;但是,迭代的值不同,for..in返回被迭代对象的键列表,而 for..of返回被迭代对象的数字属性的值列表。

这是一个演示这种区别的示例:

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属性,允许访问存储的值。

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循环,例如:

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

将生成为:

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

# 以 ECMAScript 2015 及更高版本为目标

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

Last Updated: 5/25/2023, 2:35:11 PM