迭代器是被设计专用于迭代的对象,带有特定接口。所有的迭代器对象都拥有 next() 方法,会返回一个结果对象。该结果对象有两个属性:对应下一个值的 value ,以及一个布尔类型的 done ,其值为 true 时表示没有更多值可供使用。
ES5中创建一个迭代器
function createIterator(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()); // "{done: false, value: 1}" console.log(iterator.next()); // "{done: false, value: 2}" console.log(iterator.next()); // "{done: false, value: 3}" console.log(iterator.next()); // "{done: true, value: undefined}"
ES6提供的生成器,让创建迭代器对象变得更简单。
生成器是能返回一个迭代器的函数。
生成器函数由放在function关键字之后的一个星号(*)来表示,并能使用新的yield关键字。
yield指定了迭代器在被next() 方法调用时应当按顺序返回的值。
function *createIterator(items) { for (let i = 0; i < items.length; i++) { yield items[i]; } } //创建生成器也可以使用生成器函数表达式,上面第一行代码改成 //let createIterator = function *(items) { 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}"
生成器就是函数,可以被添加到对象中。
var o = { //ES5中使用函数表达式创建生成器,如果是ES6中第一行可以简化成*createIterator(items) { createIterator: function *(items) { for (let i = 0; i < items.length; i++) { yield items[i]; } } }; let iterator = o.createIterator([1, 2, 3]);
可迭代对象与 for-of 循环
可迭代对象是包含 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); }
使用Symbol.iterator访问对象的默认迭代器
let values = [1, 2, 3]; let iterator = values[Symbol.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}"
集合的迭代器
集合的3种对象类型:数组、Map与Set都拥有如下的迭代器:
entries() :返回一个包含键值对的迭代器;
values() :返回一个包含集合中的值的迭代器;
keys() :返回一个包含集合中的键的迭代器。
当 for-of 循环没有显式指定迭代器时,每种集合类型都有一个默认的迭代器供循环使用。
values() 方法是数组与 Set 的默认迭代器,而 entries() 方法则是 Map 的默认迭代器。
let colors = [ "red", "green", "blue" ]; for (let entry of colors.entries()) { console.log(entry); } /*输出: [0, "red"] [1, "green"] [2, "blue"] */ for (let entry of colors.values()) { console.log(entry); } /*输出: "red" "green" "blue" */ for (let key of colors.keys()) { console.log(key); } /*输出: 0 1 2 */ for (let entry of colors) { console.log(entry); } /*输出: "red" "green" "blue" */
解构与 for-of 循环
Map 默认迭代器的行为有助于在 for-of 循环中使用解构。
let data = new Map(); data.set("title", "Understanding ES6"); data.set("format", "ebook"); // 与使用 data.entries() 相同 for (let [key, value] of data) { console.log(key + "=" + value); }