迭代器模式

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

应用场景
◆ jQuery each
◆ ES6 Iterator

迭代器模式符合的设计原则:
◆ 迭代器对象和目标对象分离
◆ 迭代器将使用者与目标对象隔离开
◆ 符合开放封闭原则

1. 迭代器demo

image.png
class Iterator {
    constructor(conatiner) {
        this.list = conatiner.list
        this.index = 0
    }
    next() {
        if (this.hasNext()) {
            return this.list[this.index++]
        }
        return null
    }
    hasNext() {
        if (this.index >= this.list.length) {
            return false
        }
        return true
    }
}

class Container {
    constructor(list) {
        this.list = list
    }
    getIterator() {
        return new Iterator(this)
    }
}

// 测试代码
let container = new Container([1, 2, 3, 4, 5])
let iterator = container.getIterator()
while(iterator.hasNext()) {
    console.log(iterator.next())
}

2. ES6 Iterator

ES6 Iterator为何存在?
◆ ES6语法中,有序集合的数据类型已经有很多
◆ Array Map Set String TypedArray arguments NodeList
◆ 需要有一个统一的遍历接口来遍历所有数据类型
◆ (注意,object不是有序集合,可以用Map代替)

ES6 Iterator是什么?
◆ 以上数据类型,都有[Symbol.iterator] 属性
◆ 属性值是函数,执行函数返回一个迭代器
◆ 这个迭代器就有next方法可顺序迭代子元素
◆ 可运行Array.prototype[Symbol.iterator]来测试

ES6 Iterator示例

function each(data) {
    // 生成遍历器
    let iterator = data[Symbol.iterator]()

    console.log(iterator.next())  // 有数据时返回 {value: 1, done: false}
    console.log(iterator.next())
    console.log(iterator.next())
    console.log(iterator.next())
    console.log(iterator.next())  // 没有数据时返回 {value: undefined, done: true}

    let item = {done: false}
    while (!item.done) {
        item = iterator.next()
        if (!item.done) {
            console.log(item.value)
        }
    }
}

let arr = [1, 2, 3, 4]
let nodeList = document.getElementsByTagName('p')
let m = new Map()
m.set('a', 100)
m.set('b', 200)
each(arr)
each(nodeList)
each(m)

for...of是iterator的封装,用for...of实现each

function each(data) {
    for (let item of data) {
        console.log(item)
    }
}

你可能感兴趣的:(迭代器模式)