浅谈前端设计模式4:迭代器模式

115 阅读2分钟

一、迭代器模式概念

  • 顺序遍历【有序】集合
  • 使用者无需知道集合的内部结构

二、UML类图

传统UML类图

image.png

简化后的UML类图

image.png

迭代器类代码实现

image.png

image.png

三、使用场景

1、jQuery each

如果要遍历【数组、NodeList、jQuery对象集合】,分别要使用三种方式遍历

image.png

但是如果使用jQuery转成JQuery对象集合(迭代器),则可以直接使用jQuery each遍历

image.png

2、ES6 Iterator

ES6语法中的【有序】集合数据类型有:Array、String、arguments、NodeList、Map、Set、TypedArray。(注意:object不是有序集合,可以用Map代替)

  • 以上数据类型都有[Symbol.iterator]属性。属性值是函数,执行函数返回一个迭代器
  • 这个迭代器有next方法可顺序迭代子元素

根据以上特点,我们可以重写遍历方法如下:

function each(data) {
    // 生成迭代器
    let iterator = data[Symbol.iterator]()
    
    // 初始化一个迭代结果
    let item = {done: false}
    
    // 循环迭代成员
    while (!item.done) {
        item = iterator.next()
        if (!item.done) {
            console.log(item.value)
        }
    }
}
  • 实际我们平时遍历一个有序集合并不需要自己封装一个以上的方法,其实ES6已经有了针对可迭代对象的遍历方法(for/of)。
  • 注:for/of循环要求of后面必须是【可迭代对象】,for/in循环的in后面可以是任意对象。

用ES5去写一个能够生成迭代器对象的迭代器生成函数

// 定义生成器函数,入参是任意集合
function iteratorGenerator(list) {
    // idx记录当前访问的索引
    var idx = 0
    // len记录传入集合的长度
    var len = list.length
    return {
        // 自定义next方法
        next: function() {
            // 如果索引还没有超出集合长度,done为false
            var done = idx >= len
            // 如果done为false,则可以继续取值
            var value = !done ? list[idx++] : undefined
            
            // 将当前值与遍历是否完毕(done)返回
            return {
                done: done,
                value: value
            }
        }
    }
}

var iterator = iteratorGenerator(['1号选手', '2号选手', '3号选手'])
iterator.next()
iterator.next()
iterator.next()

image.png

Generator

除了以上数据类型以外,Generator函数返回结果,也可实现Iterator接口。(Generator 已被async/await取代)

image.png