Iterators & Generators
迭代器和发生器
Iterables
如果对象具有Symbol.iterator
属性的实现,则该对象被认为是可迭代的。一些内置的类型,如Array
,Map
,Set
,String
,Int32Array
,Uint32Array
,等有自己的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..of
和for..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
另一方面,主要关注可迭代对象的值。内置对象,Map
并Set
实现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
循环以定位引擎中的内置迭代器实现。