林秀栋的技术博客

设计模式(八) 迭代器模式

html

<ul id="abc">
	<li>0</li>
	<li>1</li>
	<li>2</li>
	<li>3</li>
	<li>4</li>
	<li>5</li>
</ul>

js

//迭代器模式
//优化循环语句
var Iterator = function(items, container){
    //若存在container则获取,否则获取document
    var container = container && document.getElementById(container) || document,
        items = container.getElementsByTagName(items),
        length = items.length,
        index = 0;
    //缓存原生数组的splice方法
    var splice = [].splice;
    return {
        //获取第一个元素
        first: function(){
            index = 0;
            return items[index];
        },
        //获取最后一个元素
        last: function(){
            index = length - 1;
            return items[index];
        },
        //获取前一个元素
        pre: function(){
            if(--index > 0){
                return items[index];
            }else{
                index = 0;
                return null;
            }
        },
        //获取后一个元素
        next: function(){
            if(++index < length){
                return items[index];
            }else{
                index = length - 1;
                return null;
            }
        },
        //获取某一个元素
        get: function(num){
            index = num >= 0 ? num % length : num % length + length;
            return items[index];
        },
        //对每个元素执行某方法
        dealEach: function(fn){
            //以第二个参数为回调函数中的参数
            var args = splice.call(arguments, 1);
            for(var i = 0; i < length; i++){
                fn.apply(items[i], args);
            }
        },
        //对某个元素执行某方法
        dealItem: function(num, fn){
            fn.apply(this.get(num), splice.call(arguments, 2));
        },
        //排他方式处理某一元素
        exclusive: function(num, allFn, numFn){
            //对所有元素执行回调函数
            this.dealEach(allFn);
            //如果num类型为数组
            if(Object.prototype.toString.call(num) === "[object Array]"){
                for(var i = 0, len = num.length; i < len; i++){
                    this.dealItem(num[i], numFn);
                }
            }else{
                this.dealItem(num, numFn);
            }
        }
    }
}

var demo = new Iterator('li', 'abc');
console.log(demo.first());
console.log(demo.get(3));
//处理所有元素
demo.dealEach(function(color){
    this.style.color = color;
}, 'pink');
//排他思想处理第3个与第4个元素
demo.exclusive([2, 3], function(){
    this.innerHTML = '被排除的';
}, function(){
    this.innerHTML = '选中的';
})


//数组迭代器
var eachArray = function(arr, fn){
    //对象迭代器for中改为(var i in arr)即可(可用obj替代arr)
    for(var i = 0, len = arr.length; i < len; i++){
        //3个参数分别为this的指向,index,index对应的data
        if(fn.call(arr[i], i, arr[i]) === false){
            break;
        }
    }
}
var k = [1,2,3,4,5];
eachArray(k, function(i, data){
    console.log(i, data);
})


//同步变量迭代器
//有时需要获取对象中的某个值,但该值可能不存在导致报错
//而使用a && a.b && a.b.c代码太过冗余
var A = {
    B: {},
    C: {
        D: 'hello world'
    }
}
AGetter = function(key){
    if(!A){
        return undefined;
    }
    var result = A;
    key = key.split('.');
    for(var i = 0, len = key.length; i < len; i++){
        if(result[key[i]] !== undefined){
            result = result[key[i]];
        }else{
            return undefined;
        }
    }
    return result;
}
console.log(AGetter('C.D'));
//修改或新增A中的属性
ASetter = function(key, val){
    if(!A){
        return undefined;
    }
    var result = A;
    key = key.split('.');
    for(var i = 0, len = key.length; i < len - 1; i++){
        if(result[key[i]] === undefined){
            result[key[i]] = {};
        }
        if(!(result[key[i]] instanceof Object)){
            throw new Error('A.' + key.splice(0, i + 1).join('.') + 'is not Object');
        }
        result = result[key[i]];
    }
    return result[key[i]] = val;
}
ASetter('B.E.G', 'add');
console.log(A);
//不允许为值类型添加属性
//console.log(ASetter('C.D.K', 'add2'));


//分支循环嵌套
//对很多组数据进行处理时,数据量大时会有很多不必要的消耗
/*for(...){
    switch(t){
        case '1':
            //...
        case '2':
            //...
        break;
    }
}*/
//使用迭代器模式
//先判断分支再循环,这里每组需要有规律,比如循环中i每次+4执行
/*var Deal = function(){
    var method = {
        //默认
        'default': function(){},
        '1': function(){},
        '2': function(){}
    };
    return function(type){
        return method[type] || method['default'];
    }
}
//迭代器处理数据
function eachData(fn){
    for(...; i += 4){
        fn(i);
    }
}
eachData(Deal(t));*/