迭代器(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 }
简而言之,迭代器是关于如何遍历数据结构的规则,而生成器提供了一种有效而优雅的实现这些规则的方法。