起源何为迭代器?迭代器是被设计专用于迭代的对象,带有特定接口。所有的迭代器对象都拥有 next() 方法,会返回一个结果对象。该结果对象有两个属性:对应下一个值的 value ,以及一个布尔类型的 done ,其值为 true 时表示没有更多值可供使用。迭代器持有一个指向集合位置的内部指针,每当调用了 next() 方法,迭代器就会返回相应的下一个值。记住这些后,在 ES5 中创建一个迭代器就相当简单了:function ceateIterator(items) { var i = 0; return { next: function() { var done = (i >= items.length); var value = !done ? items[i++]: undefined; return { done: done, value: value }; } };}var iterator = createIterator([1, 2, 3]);console.log(iterator.next()); // “{ value: 1, done: false }“console.log(iterator.next()); // “{ value: 2, done: false }“console.log(iterator.next()); // “{ value: 3, done: false }“console.log(iterator.next()); // “{ value: undefined, done: true }”// 之后的所有调用console.log(iterator.next()); // “{ value: undefined, done: true }“可迭代对象 与 for-of循环与迭代器紧密相关的是,可迭代对象( iterable )是包含 Symbol.iterator 属性的对象。这个 Symbol.iterator 知名符号定义了为指定对象返回迭代器的函数。在 ES6 中,所有的集合对象(数组、 Set 与 Map )以及字符串都是可迭代对象,因此它们都被指定了默认的迭代器。可迭代对象被设计用于与 ES 新增的 for-of 循环配合使用。for-of在循环每次执行时会调用可迭代对象next()方法,并将结果value值保存在一个变量上,循环过程到done变成true时停止。let values = [1, 2, 3];for (let num of values) {console.log(num);}此代码输出如下123这个 for-of 循环首先调用了 values 数组的 Symbol.iterator 方法,获取了一个迭代器(对 Symbol.iterator 的调用发生在 JS 引擎后台)。接下来 iterator.next() 被调用,迭代器结果对象的 value 属性被读出并放入了 num 变量。 num 变量的值开始为 1 ,接下来是 2 ,最后变成 3 。当结果对象的 done 变成 true ,循环就退出了,因此 num 绝不会被赋值为 undefined 。访问默认迭代器你可以使用 Symbol.iterator 来访问对象上的默认迭代器,就像这样:let values = [1, 2, 3];let iterator = valuesSymbol.iterator;console.log(iterator.next()); // “{ value: 1, done: false }“console.log(iterator.next()); // “{ value: 2, done: false }“console.log(iterator.next()); // “{ value: 3, done: false }“console.log(iterator.next()); // “{ value: undefined, done: true }“既然 Symbol.iterator 指定了默认迭代器,你就可以使用它来检测一个对象是否能进行迭代,正如下例:function isIterable(object) {return typeof object[Symbol.iterator] === “function”;}console.log(isIterable([1, 2, 3])); // trueconsole.log(isIterable(“Hello”)); // trueconsole.log(isIterable(new Map())); // trueconsole.log(isIterable(new Set())); // trueconsole.log(isIterable(new WeakMap())); // falseconsole.log(isIterable(new WeakSet())); // false集合的迭代器ES6 具有三种集合对象类型:数组、 Map 与 Set 。这三种类型都拥有如下的迭代器,有助于探索它们的内容:entries() :返回一个包含键值对的迭代器;values() :返回一个包含集合中的值的迭代器;keys() :返回一个包含集合中的键的迭代器;entries()迭代器entries() 迭代器会在每次 next() 被调用时返回一个双项数组,此数组代表了集合中每个元素的键与值:对于数组来说,第一项是数值索引;对于 Set ,第一项也是值(因为它的值也会被视为键);对于 Map ,第一项就就是键。let colors = [ “red”, “green”, “blue” ];let tracking = new Set([1234, 5678, 9012]);let data = new Map();data.set(“title”, “Understanding ES6”);data.set(“format”, “ebook”);for (let entry of colors.entries()) {console.log(entry);}for (let entry of tracking.entries()) {console.log(entry);}for (let entry of data.entries()) {console.log(entry);}输出内容如下:[0, “red”][1, “green”][2, “blue”][1234, 1234][5678, 5678][9012, 9012][“title”, “Understanding ES6”][“format”, “ebook”]values() 迭代器values() 迭代器仅仅能返回存储在集合内的值,例如:let colors = [ “red”, “green”, “blue” ];let tracking = new Set([1234, 5678, 9012]);let data = new Map();data.set(“title”, “Understanding ES6”);data.set(“format”, “ebook”);for (let value of colors.values()) {console.log(value);}for (let value of tracking.values()) {console.log(value);}for (let value of data.values()) {console.log(value);}此代码输出了如下内容:“red"“green"“blue"123456789012"Understanding ES6"“ebook"keys() 迭代器keys() 迭代器能返回集合中的每一个键。对于数组来说,它只返回了数值类型的键,永不返回数组的其他自有属性; Set 的键与值是相同的,因此它的 keys() 与 values() 返回了相同的迭代器;对于 Map , keys() 迭代器返回了每个不重复的键。这里有个例子演示了这三种情况:let colors = [ “red”, “green”, “blue” ];let tracking = new Set([1234, 5678, 9012]);let data = new Map();data.set(“title”, “Understanding ES6”);data.set(“format”, “ebook”);for (let key of colors.keys()) {console.log(key);}for (let key of tracking.keys()) {console.log(key);}for (let key of data.keys()) {console.log(key);}本例输出了如下内容:012123456789012"title"“format”
...