完全理解Iterator模式

首先来看看别人对Iterator都是怎么理解的?

Iterator是这样一种机制。
它是一种接口,为各类不一样的数据结构提供统一的访问机制。
任何数据结构只要部署Iterator接口,就能够完成遍历操做。
tips: 遍历操做就是能够依次处理该数据结构的全部成员。 ---阮一峰ES6入门node


在js中,Iterator是一个对象,它定义一个序列,并在终止时可能返回一个返回值。 具体地说,迭代器经过使用next()方法实现Iterator protocol的任何一个对象。这个对象长这个样子{value: '任意的值', done: 'true或false'}jquery


个人理解

Iterator是这样一种机制:编程

  1. 顺序访问一个集合
  2. 使用者无需知道集合的内部结构(封装)

举个例子:数据结构

/* 针对一个仅有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已经帮咱们实现一种方法。ui

//假设已经引入了jquery
function each(data) {
    var $data = $(data); //[生成迭代器] 这个$(data)对象就是某种意义上的迭代器
    $data.each(function (key, val) {
        console.log(key, val)
    })
}
复制代码

$(data)这个对象的好处是:this

  1. 它能够顺序遍历有序集合
  2. 使用者没必要知道集合内部结构

UML类图spa

// 迭代器生成
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())
}
复制代码

场景

  1. jQuery each
  2. 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 接口,即返回了一个迭代器
复制代码

设计原则验证

  • 迭代器对象和目标对象分离
  • 迭代器将使用者与目标对象隔离开
  • 符合开放封闭原则
相关文章
相关标签/搜索