Iterators & Generators

迭代器和发生器

Iterables

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

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循环生成一个简单的for..of循环,例如:

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循环以定位引擎中的内置迭代器实现。