可迭代对象
如果一个对象实现了 Symbol.iterator
属性,则该对象被认为是可迭代的。一些内置类型,如 Array
、Map
、Set
、String
、Int32Array
、Uint32Array
等,已经实现了 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..of
与 for..in
语句
for..of
和 for..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
主要关注可迭代对象的**值**。内置对象,如 Map
和 Set
,实现了 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
循环来针对引擎中的内置迭代器实现。