七、迭代器和生成器

7.1 遍历

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

7.1.1 Iterable接口

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

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

7.1.2 for..of 声明

for...of在一个可迭代对象上循环,调用对象上的Symbol.iterator属性。下面是一个关于数组的简单for.of循环。

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

7.1.3 for..offor..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"
}

7.2 代码生成

7.2.1 生成目标 ES5 和 ES3

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

例如,编译器将为for...的循环生成一个简单的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);
}

7.2.2 ECMAScript 2015 和 更高版本

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

特别声明: 本文转自 古艺散人老师 ,如有需要可前往原文预览查看。