17-设计模式-迭代器模式(设计模式学习笔记)

163 阅读2分钟

迭代器模式

提供一种方法,顺序访问一个聚合对象中各个元素,而又无需暴露该对象的内部表示。

迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

模拟一个迭代器对象

    let arr = [1,2,3,4] // 数组集合1
    let arr2 = ["一","二","三","四"] // 数组集合2

    // 手写模拟一个迭代器
    class Iterator{ // 迭代器类
        constructor(list){ // 接收获取到的集合对象
            this.list = 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 // 否则返回true
        }
    }
    let iter = new Iterator(arr) // 实例化迭代器对象,传入接收的集合
    let iter1 = new Iterator(arr2)

    // 每次要迭代时,就调用它的迭代方法,调用几次迭代几次
    console.log(iter.next()) // 1
    console.log(iter.next()) // 2
    console.log(iter.next()) // 3
    console.log(iter.next()) // 4
    console.log(iter.next()) // null

    // 用while循环来调用方法遍历
    while(iter1.hasNext()){
        console.log(iter1.next()) // 打印 一 二 三 四
    }

使用ES6中的iterator封装一个遍历方法each

    // 使用es6中的iterator方法手动封装一个遍历方法each
    function each(list){
        let iter = list[Symbol.iterator]() // list集合对象的Symbol方法返回一个函数,这个函数执行,使其返回一个迭代器给iter
        let item = {done:false} // 写一个标识,默认为false,表示未遍历完成
        while(!iter.done){ // 当还未遍历完成时
            item = iter.next() // next方法是迭代器自带的方法
            if(!item.done){
                console.log(item.value)
            }
        }
    }

    let map = new Map() //实例生成一个对象map
    map.set("a",1) //往map对象中创建键值对
    map.set("b",2)
    each(map) //each函数中传入map集合对象,就可以迭代

万章老师的迭代器模式代码

let obj = {
	data: [ 'hello', 'world' ],
	[Symbol.iterator]() {
		const self = this;
		let index = 0;
		return {
			next() {
				if (index < self.data.length) {
					return {
						value: self.data[index++],
						done: false
					};
				} else {
					return { value: undefined, done: true };
				}
			}
		};
	}
};