首先来看看别人对Iterator都是怎么理解的?
Iterator是这样一种机制。
它是一种接口,为各种不同的数据结构提供统一的访问机制。
任何数据结构只要部署Iterator接口,就可以完成遍历操作。
tips: 遍历操作就是可以依次处理该数据结构的所有成员。 ---阮一峰ES6入门
在js中,Iterator是一个对象,它定义一个序列,并在终止时可能返回一个返回值。 具体地说,迭代器通过使用next()方法实现Iterator protocol的任何一个对象。这个对象长这个样子{value: '任意的值', done: 'true或false'}
我的理解
Iterator是这样一种机制:
- 顺序访问一个集合
- 使用者无需知道集合的内部结构(封装)
举个例子:
/*
针对一个仅有3个<a>target</a>标签的页面来说
*/
var arr = [1, 2, 3];
var nodeList = document.getElementsByTagName('p');
var $p = $('a')
// 需要对这3种数据结构进行遍历
arr.forEach(function (item) {console.log(item)})
for (let i = 0,len = nodeList.length; i < len; i++) {console.log(nodeList(i))}
$a.each(function (key, p) {console.log(key, p)})
要对这3种数据结构进行遍历,所使用的编程方式是不一样的。
但是这3种数据结构是什么样我们是提前知道的。
现在提出一个问题,能否有这样一种函数,能对这三种数据结构进行统一的遍历处理。
其实jquery已经帮我们实现一种方法。
//假设已经引入了jquery
function each(data) {
var $data = $(data); //[生成迭代器] 这个$(data)对象就是某种意义上的迭代器
$data.each(function (key, val) {
console.log(key, val)
})
}
$(data)这个对象的好处是:
- 它可以顺序遍历有序集合
- 使用者不必知道集合内部结构
UML类图

// 迭代器生成
class Iterator {
constructor(container) {
this.list = container.list
this.index = 0
}
next() {
if (this.hasNext()) {
return {value: this.list[this.index++], done: false}
}
return {done: true}
}
hasNext() {
if (this.index >= this.list.length) {
return false
}
return true
}
}
class Container {
constructor(list) {
this.list = list
}
//生成迭代器
getIterator() {
return new Iterator(this)
}
}
// 目标对象
let arr = [1, 2, 3, 4, 5, 6];
// 迭代器模式
let container = new Container(arr);
//生成迭代器对象
let iterator = container.getIterator();
while (iterator.hasNext()) {
console.log(iterator.next())
}
场景
- jQuery each
- ES6 Iterator
ES6 Iterator 为何存在?
- ES6 语法中,有序集合的数据类型已经很多
- Array Map Set String TypedArray arguments NodeList
- 需要有一个统一的遍历接口来遍历所有数据类型
- 以上数据类型,都有[Symbol.iterator]属性
- 属性值是函数,执行函数返回一个迭代器
- 这个迭代器就有next方法可顺序迭代子元素
// ES6 Iterator示例
function each(data, callback) {
//生成迭代器
let iterator = data[Symbol.iterator]();
let item = {done: false};
while (!item.done) {
item = iterator.next();
if (!item.done) {
callback(item.value);
}
}
}
//ES6 实现
function each(data, callback) {
for (let item of data) {
callback(item)
}
}
Iterator 和 Generator
- Iterator的价值不限于上述几个类型的遍历
- 还有Generator函数的使用,Generator是生成器,即生成一个迭代器
- 即只要返回的数据格式符合Iterator接口的要求
- 即可使用Iterator语法,这就是迭代器模式
funciton* helloworldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloworldGenerator();
hw[Symbol.iterator] //f [Symbol.iterator]() { [native code] }
//可以看到,Generator函数返回的结果,也实现了 Iterator 接口,即返回了一个迭代器
设计原则验证
- 迭代器对象和目标对象分离
- 迭代器将使用者与目标对象隔离开
- 符合开放封闭原则