迭代器与生成器
Iterators and Generators
可迭代对象(Iterables)
在对象有着Symbol.iterator
属性时,其就被认为是可迭代的。一些内建类型,比如Array
、Map
、Set
、String
、Int32Array
、Uint32Array
等,都已经有着其已实现的Symbol.iterator
属性。对象上的Symbol.iterator
函数,赋值返回要迭代的值的清单(Symbol.iterator
function on an object is responsible for returning the list of values to iterate on)。
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
则是返回的所迭代对象数值属性的 值 的清单(Both for..of
and for..in
statements iterate over lists; the values iterated on are differenct 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 interatd)。
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
属性的内建对象,才允许对存储值的访问(Built-in objects like Map
and Set
implement Symbol.iterator
property allowing access to stored values)。
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
在生成目标代码为ES5或ES3时,只允许在Array
类型上使用迭代器。就算非数组值实现了Symbol.iterator
属性, 在它们上使用for..of
循环都是错误的。
编译器将为for..of
循环生成一个简单的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(_i);
}
目标代码为ECMAScript2015或更高版本时
在以兼容ECMAScript2015引擎为目标时,编译器将生成for..of
循环,从而以引擎中的内建迭代器实现为目标。