迭代器代理
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示。
迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。
jQuery中的迭代器
比如jQuery中的$.each函数,其中回调函数中的参数i为当前索引,n为当前元素。
$.each([1,2,3],function(i,n){ console.log('当前下标为:'+i); console.log('当前值:'+n); })
实现自己的迭代器
实现each函数,each函数接受2个参数,第一个为被循环的数组,第二个为循环中的每一步后将被触发的回调函数:
var each = function(ary,callback){ for(var i = 0,l = ary.length;i<l;i++){ callback.call(arr[i],i,ary[i]) } } each([1,2,3],function(i,n){ alert([i,n]) })
内部迭代和外部迭代器
内部迭代器
内部迭代器已经定义好了迭代规则,完全接手整个迭代过程,外部只需要一次初始调用。
上面的each函数就是内部迭代器
外部迭代器
外部迭代器必须显示地请求迭代下一个元素。
外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,可以手工控制迭代的过程或者顺序。
var Iterator = function(obj){ var current = 0; var next = function(){ current += 1 } var isDone = function(){ return current >= obj.length } var getCurrItem = function(){ return obj[current] } return { next: next, isDone: isDone, getCurrItem: getCurrItem, length: obj.length } } 再看看如何改写compare函数: var compare = function(iterator1,iterator2){ if(iterator1.length !== iterator2.length){ alert('iterator1和iterator2不相等') } while(!iterator1.isDone()&& !iterator2.isDone()){ if(iterator1.getCurrItem() != iterator2.getCurrItem()){ throw new Error('iterator1和iterator2不相等') } iterator1.next() iterator2.next() } alert('iterator1和iterator2相等') } var iterator1 = Iterator([1,2,3]) var iterator2 = Iterator([1,2,3]) compare(iterator1,iterator2) // 输出:iterator1 和 iterator2相等
外部迭代器虽然调用方式相对复杂,但适用性更广,能满足更多变的需求
内部迭代器和外部迭代器在实际生产中没有优劣之分,究竟使用哪个要根据需求场景定
迭代类数组对象和字面量对象
迭代器模式不仅可以迭代数组,还可以迭代一些类数组的对象。
比如 arguments、{"0":'a',"1":'b'}等,只要被迭代的聚合对象拥有length属性而且可以用下标访问,就可以被迭代。
倒序迭代器
var reverseEach = function(ary,callback){ for(var l = ary.length-1;l>=0;l--){ callback(l,ary[l]) } } reverseEach([0,1,2],function(i,n){ console.log(n);// 分别输出:2,1,0 })
中止迭代器
迭代器可以像普通for循环中的break一样,提供一种跳出循环的方法。
var each = function(ary,callback){ for(var i = 0,l=ary.length;i<l;i++){ if(callback(i,ary[i])==false){ break; } } } each([1,2,3,4,5],function(i,n){ if(n>3){ // n大于3的时候终止循环 return false; } console.log(n) // 分别输出:1,2,3 })