迭代器和生成器

迭代器

¥Iterables

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

¥An object is deemed iterable if it has an implementation for the Symbol.iterator property. Some built-in types like Array, Map, Set, String, Int32Array, Uint32Array, etc. have their Symbol.iterator property already implemented. Symbol.iterator function on an object is responsible for returning the list of values to iterate on.

Iterable 接口

¥Iterable interface

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

¥Iterable is a type we can use if we want to take in types listed above which are iterable. Here is an example:

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

for..of 语句

¥for..of statements

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

¥for..of loops over an iterable object, invoking the Symbol.iterator property on the object. Here is a simple for..of loop on an array:

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

for..offor..in 语句

¥for..of vs. for..in statements

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

¥Both for..of and for..in statements iterate over lists; the values iterated on are different though, for..in returns a list of keys on the object being iterated, whereas for..of returns a list of values of the numeric properties of the object being iterated.

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

¥Here is an example that demonstrates this distinction:

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

¥Another distinction is that for..in operates on any object; it serves as a way to inspect properties on this object. for..of on the other hand, is mainly interested in values of iterable objects. Built-in objects like Map and Set implement Symbol.iterator property allowing access to stored values.

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"
}

代码生成

¥Code generation

针对 ES5 和 ES3

¥Targeting ES5 and ES3

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

¥When targeting an ES5 or ES3-compliant engine, iterators are only allowed on values of Array type. It is an error to use for..of loops on non-Array values, even if these non-Array values implement the Symbol.iterator property.

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

¥The compiler will generate a simple for loop for a for..of loop, for instance:

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

将生成为:

¥will be generated as:

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

以 ECMAScript 2015 及更高版本为目标

¥Targeting ECMAScript 2015 and higher

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

¥When targeting an ECMAScript 2015-compliant engine, the compiler will generate for..of loops to target the built-in iterator implementation in the engine.