所有迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true。
ES5中模拟一个迭代器:
function createIterator(items) { var i = 0; return { next: function() { var done = (i >= items.length); var value = !done ? items[i++] : underfined; 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: true} console.log(iterator.next); // {value: underfined, done: true}!!!注意:yield关键字只可在生成器内部使用,在其他地方使用会导致程序抛出语法错误。如:
function* createIterator(items) { items.forEach(function(item) { // 语法错误 yield item + 1; }) }可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。Symbol.iterator通过指定的函数可以返回一个作用于附属对象的迭代器。
由于生成器默认会为Symbol.iterator属性赋值,因此所有通过生成器创建的迭代器都是可迭代对象。在ES6中所有集合对象、字符串都是可迭代对象。
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 }默认情况下,开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,则可以将其变为可迭代对象
let collection = { items: [], * [Symbol.iterator]() { for (let item of this.items) { yield item; } } }; collection.items.push(1); collection.items.push(2); collection.items.push(3); for (let x of collection) { console.log(x); } // 1 // 2 // 3在ES6中对集合对象都内建了三种迭代器(数组、Set、Map)。
entries() 返回一个迭代器,其值为多个键值对。values() 返回一个迭代器,其值为集合的值。keys() 返回一个迭代器,其值为集合中的所有键名。在for-of循环中,数组和Set默认是values(),Map默认是entries()
let colors = ['red', 'green', 'blue']; for (let entry of colors.entries()) { console.log(entry); // [ 0, 'red' ] [ 1, 'green' ] [ 2, 'blue' ] } // 其余的就不一一举例了,有兴趣的自行体验如果给迭代器的next() 方法传递参数,则这个参数的值就会代替生成器内部上一条yield语句的返回值。
第一次调用next() 方法前不会执行任何yield语句,因此在第一次调用next()方法时传递参数是毫无意义的。
function* createIterator() { let first = yield 1; let second = yield first + 2; // 4+2 yield second + 3; // 5+3 } let iterator = createIterator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next(4)); // { value: 6, done: false } console.log(iterator.next(5)); // { value: 8, done: false } console.log(iterator.next()); // { value: undefined, done: true }