迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

关于这个定义的个人理解,聚合对象是指可遍历的对象,一般具有的特征就是可用下标访问且具有length属性。

不暴露该对象的内部表示是指在通过迭代器访问聚合中元素时,迭代器访问接口统一,不用关心对象内部细节。

迭代器分类

内部迭代器

内部迭代器是指外界不用关心迭代器内部实现,初始调用一次迭代器就可以实现遍历功能了。
    
        let each=function (ary,cb) {
            for(let i=0,len=ary.length;i<len;i++){
                cb(ary[i],i,ary[i]);
            }
        }
        each([4,5,6],function (i,v) {
            console.log(i,v);
        })
        // 4 0
        // 5 1
        // 6 2

外部迭代器

外部迭代器是指必须显式的请求迭代下一个元素

    class Iterator{
    
        constructor(obj){
            this.obj=obj;
            this.current=0;
        }
        next() {
            this.current+=1;
        }
        isDone() {
            return this.current>=this.obj.length
        }
        getCurrentItem () {
            return this.obj[this.current];
        }
    }
    
    let iterator1=new Iterator([1,2,3]);
    console.log(iterator1.next())
    console.log(iterator1.getCurrentItem())  //2
    

外部迭代器相对内部迭代器的优点是,可以手工控制迭代过程。虽然灵活,但是调用复杂度增加,必须熟悉迭代器接口。

实战应用

案例一

let getUploadObjA=function () {
    try{
        throw 'testA';
    }catch (e){
        return false;
    }
}
let getUploadObjB=function () {
    return "testB";
}
let getUploadObjC=function () {
    try{
        throw 'testC';
    }catch (e){
        return false;
    }
}

let iteratorUploadObj=function () {
    for(let i=0,len=arguments.length;i<len;i++){
        var uploadObj=arguments[i]();
        if(uploadObj!=false){
            return uploadObj;
        }
    }

}
let upLoadObj=iteratorUploadObj(getUploadObjA,getUploadObjB,getUploadObjC);

console.log(upLoadObj)  //testB

说明 其实在日常开发中,例如上传文件有很多方式,插件,h5,input的file方式等等,根据兼容性,设定支持的先后顺序放在迭代器中,以后维护时时若有其它方式
直接往迭代器中添加就行,非常方便。总的来说就是方便代码维护且具有良好的拓展性。

案例2

let isType=function (type) {
    return function (obj) {
        return Object.prototype.toString.call(obj)==='[object '+type+"]";
    }
}

let isWindow=isType('Window');

function isArraylike(obj) {
    let len='length' in obj &&obj.length;
    let typeObj=typeof obj;
    let typeLen=typeof len;
    
    if(typeObj ==='function' ||isWindow(obj)){
        return false;
    }
    //Element
    if(obj.nodeType==1&&len){
        return true;
    }
    return typeObj === 'array' ||len===0 ||typeLen =='number' &&len>0 &&(len-1) in obj;
}
each=function (obj,cb) {
    let value,
        i=0,
        length=obj.length,
        isArray=isArraylike(obj);
    if(isArray){
        for(;i<length;i++){
            value=cb.call(obj[i],i,obj[i]);
            if(value==false){
                break;
            }
        }
    }else{
        for(i in obj){
            value=cb.call(obj[i],i,obj[i]);
            if(value==false){
                break;
            }
        }
    }
}
//可以迭代标准数组   以及一些arguments,nodelist等具备可迭代特征的对象
// case1:
each([1,2,3],function(i,v){
    console.log(i,v);
})
// 0 1
// 1 2
// 2 3
// case2
each({
    0:"4",
    1:"5",
    2:"6",
    length:3
},function(i,v){
    console.log(i,v);
})

// 0 "4"
// 1 "5"
// 2 "6"

说明 上面实现了一个通用的迭代器。


jsdt
4.9k 声望3.9k 粉丝

make a little progress every day


« 上一篇
策略模式
下一篇 »
Genrator浅析