JavaScript设计模式之迭代器模式

发布于 / 学习

介绍

  • 顺序访问一个集合(有序的:Array)
  • 使用者无需知道集合的内部结构

实例

  • 使用jQ演示
    <p>jq each</p>
    <p>jq each</p>
    <p>jq each</p>
    var arr = [1,2,3]
    var nodeList = document.getElementsByTagName('p')
    var $p = $('p')

    arr.forEach(function (item) {
        console.log(item);
    })

    var i , length = nodeList.length
    for (i = 0;i<length;i++){
        console.log(nodeList[i]);
    }

    $p.each(function (key,p) {
        console.log(key,p)
    })
  • 上述的实例中,如果想遍历arr,a标签需要三种方式。这里定义一个迭代器模式的方法统一这三个方法
     //定义一个each 方法
    function each(data) {
        var $data = $(data) //生成迭代器
        $data.each(function (key,val) {
            console.log(key,val)
        })
    }

    each(arr)
    each(nodeList)
    each($p)

UML类图

image

代码演示

    class Container {
        constructor(list) {
            this.list = list
        }

        //生成遍历器
        getInterator() {
            return new Iterator(this.list)
        }
    }

    class Iterator {
        constructor(container) {
            this.list = container.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
        }
    }

    //test
    let arr = [1,2,3,4,5]
    let container = new Container(arr)
    let iterator = container.getInterator()
    while (iterator.hasNext()) {
        console.log(iterator.next())
    }

场景

  • jQuery each
  • ES6 Iterator

ES6 Iterator

  • Es6中,有序集合的数据类型很多,所以必须有一种迭代模式来遍历
  • 使用`[Symbol.Iterator]属性
  • 属性值是函数,执行函数返回一个迭代器
  • 返回的迭代器有next()这个方法可顺序迭代子元素
    image
     //首先 返回[Symbol.Iterator]
    function each(data) {
        let iterator = data[Symbol.iterator]()
        // console.log(iterator.next())
        // console.log(iterator.next())
        // console.log(iterator.next())
        // console.log(iterator.next())
        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('a')
    let m = new Map()
    m.set('a',100)
    m.set('b',100)
    m.set('c',100)

    each(arr)
    // each(nodeList)
    each(m)

    //console

image
– 实际上ES6已经实现了迭代器的方法for of

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

     each2(arr)
    // each(nodeList)
    each2(m)

image

ES6 Iterator与Generator

  • Iterator的价值不限于上述的数据遍历
  • 还有Generator函数的使用
  • 即只要返回的数据符合Iterator接口的要求
  • 即可使用Iterator语法
    image
  • 可以看到也实现了[Symbol.iteartor]

代码

https://github.com/ahwgs/design-pattern-learning/tree/master/10.JavaScript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E8%BF%AD%E4%BB%A3%E5%99%A8%E6%A8%A1%E5%BC%8F

本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可
本文链接: https://www.ahwgs.cn/javascriptshejimoshizhidiedaiqimoshi.html