迭代器(Iterator)
迭代器是一种特定的设计模式,用于依次访问集合的元素而不必暴露其底层的表现形式。ECMAScript 6(ES6)引入了内建的迭代器,该标准定义了Iterable
和Iterator
协议。
Iterable协议
- 任何对象实现
[Symbol.iterator]
方法,该方法必须返回一个迭代器,那么它就符合Iterable
协议。 - 内建的可迭代对象有
Array
,Map
,Set
,String
等。
Iterator协议
- 一个对象如果有
next()
方法,此方法无参数或接受一个值,返回一个具备value
和done
两个属性的对象,那么这个对象就是迭代器。 value
属性表示下一个被返回的值,done
是一个布尔值,当迭代器可被继续迭代时为false
,迭代器被耗尽时为true
。
简单迭代器实例:
function createIterator(array) {
let nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{ value: array[nextIndex++], done: false } :
{ done: true };
}
};
}
const it = createIterator([1, 2, 3]);
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { done: true }
生成器(Generator)
生成器是ES6中引入的一种特殊函数,它可以通过yield
关键字将函数的执行暂停,并在必要时通过生成器对象的next()
方法再次进入函数。生成器无需一次返回所有结果,而是按需“生成”结果,这对于处理大数据集或无限数据流尤为有用。
生成器函数通过function*
声明,而且可以包含一个或多个yield
表达式。
生成器实例:
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
const gen = generatorFunction();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { done: true }
生成器也符合迭代器协议,因此任何被yield
的值都会遵循Iterator
返回值的规定。
使用生成器可以非常方便地实现自定义迭代器。如下实现一个通过生成器模拟迭代器的例子:
function* createGenerator(array) {
for(let i = 0; i < array.length; i++) {
yield array[i];
}
}
const gen = createGenerator([1, 2, 3]);
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { done: true }
简而言之,迭代器是关于如何遍历数据结构的规则,而生成器提供了一种有效而优雅的实现这些规则的方法。