再起航,我的学习笔记之JavaScript设计模式25(迭代器模式)

来源:互联网 发布:软件行业目标市场分析 编辑:程序博客网 时间:2024/04/16 17:49
## 迭代器模式 ### 概念介绍 **迭代器模式(Iterator):** 在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素。 ### 迭代器 程序中的循环是一种利器,循环语句也使我们程序开发更简洁高效,但是有时一遍又一遍的重复性循环却让代码显得循环不堪。 这个时候我们就可以用迭代器来简化我们的循环遍历操作,下面我们创建一个迭代器类。 ``` //迭代器 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]; }, //获取最后一个元素 second:function(){ index=length-1; return items[index]; }, //获取前一个元素 pre:function(){ if(--index>0){ return items[index]; }else{ index=0; return null; } }, //获取后一个元素 next:function(){ if(++index=0?num%length:num%length+length; console.log(index); 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){="" 第三个参数开始为回调函数中参数="" 用this.get方法设置index索引值="" 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]"){="" 遍历num数组="" for(var="" i="0;i<num.length;i++){" this.dealitem(num[i],numfn);="" }else{="" 处理第num个元素="" this.dealitem(num,numfn);="" ```="" 页面元素如下:="" ```html=""
  • 1
  • 2
  • 3
  • 4``` 好了我们的迭代器就完成了,我们试着调用一下 ``` var test=new Iterator("li","container"); //我们先试试获取元素 console.log(test.first()); console.log(test.pre()); console.log(test.next()); console.log(test.get(2000)); ``` ![](http://images2017.cnblogs.com/blog/774226/201709/774226-20170924221846134-1244689007.png) 我们再来处理所有元素 ``` test.dealEach(function(text,color){ this.innerHTML=text; this.style.background=color; },'背景变色','#dddddd'); ``` ![](http://images2017.cnblogs.com/blog/774226/201709/774226-20170924221900056-1142194150.png) 接着我们选中前两个元素 ``` test.exclusive([0,1],function(){ this.innerHTML='被排除的'; this.style.background='green'; },function(){ this.innerHTML='选中的'; this.style.background='red'; }) ``` ![](http://images2017.cnblogs.com/blog/774226/201709/774226-20170924221914009-1289803387.png) 通过迭代器提供的接口方法就能轻易地访问聚合对象中的每一个元素。甚至不需要知道聚合对象的内部的具体结构。 ### 数组迭代器 我们知道在低版本的IE下是不支持each方法的,那么我们就可以通过迭代器的思想定义一个数组迭代器来完成each操作 ``` var eachArray=function(arr,fn){ for (var i=0;i<arr.length;i++) {="" 依次执行回调函数,注意回调函数中传入的参数第一个为索引,第二个为索引对应的值="" if(fn.call(arr[i],i,arr[i])="==false){" break;="" }="" ```="" 我们来测试一下="" for(var="" arr="[],i=0;i<5;arr[i++]=i);" eacharray(arr,function(i,data){="" console.log(i,data);="" })="" ![](http:="" images2017.cnblogs.com="" blog="" 774226="" 201709="" 774226-20170924221926650-214230657.png)="" ###="" 对象迭代器="" 对象迭代器与数组迭代器比较类似,但传入回调函数中的为对象的属性与对象的属性值="" var="" eachobject="function(obj,fn){" i="" in="" obj){="" if(fn.call(obj[i],i,obj[i])="==false){" 我们再来看看="" obj="{a:1,b:2,c:3}" eachobject(obj,function(i,data){="" });="" 774226-20170924221934556-1514738597.png)="" 解决分支循环嵌套="" 当然我们也能用迭代器解决分支循环嵌套,比如我们使用canvas来处理图片像素绘制如下效果="" 774226-20170924221957415-1639708709.png)="" 页面元素如下:=""   ``` ``` window.onload=function(){ //获取画布 var canvas=document.getElementsByTagName('canvas')[0], //获取图片 img=document.images[0], //获取并设置宽度 width=(canvas.width=img.width*2)/2, //获取并设置高度 height=canvas.height=img.height, //获取渲染上下文 ctx=canvas.getContext('2d'); //绘制图片 function dealImage(t,x,y,w,h,a){ //获取画布图片数据 var canvasData=ctx.getImageData(x,y,w,h); //获取像素数据 var data=canvasData.data; //遍历每组像素数据(4个数据表示一个像素点数据,分别代表红色、绿色、蓝色、透明度) for (var i=0;i<data.length;i+=4) {="" switch(t){="" case="" 'red':="" data[i+1]="0;" data[i+2]="0;" data[i+3]="a;" break;="" 'green'="" :="" data[i]="0;" 'blue':="" 'gray':="" var="" num="parseInt((data[i]+data[i+1]+data[i+2])/3);" }="" 绘制处理后的图片="" ctx.putimagedata(canvasdata,width+x,y);="" 为图片添加特效="" dealimage('gray',0,0,width,height,255);="" ```="" 然而我们发现,这种逻辑并不是最优的,因为每一次遍历都要进行一次分支判断,假如有一张比较大的图片会产生很多不必要的消耗,但是我们可以将循环遍历抽象出来作为一个迭代器存在,每次循环都执行传入迭代器中的某一固定算法,对于特效算法我们可以设置在策略对象中实现,通过策略模式与迭代器模式的综合运用就可以解决分支判断问题="" function="" dealimage(t,x,y,w,h,a){="" canvasdata="ctx.getImageData(x,y,w,h)," data="canvasData.data;" 策略模式封装算法="" deal="function(){" method="{" 'default':function(i){="" return="" method['gray'](i);="" },="" 'red':function(i){="" 'green':function(i){="" 'gray':function(i){="" };="" 主函数,通过给定类型返回对应滤镜算法="" function(type){="" method[type]||method['default'];="" }();="" 迭代器处理数据="" eachdata(fn){="" for="" (var="" i="0;i<data.length;i+=4)" fn(i);="" eachdata(deal(t));="" ![](http:="" images2017.cnblogs.com="" blog="" 774226="" 201709="" 774226-20170924222023040-778251259.png)="" ###="" 总结="" 通过迭代器我们可以顺序地访问一个聚合对象中的每一个元素。在开发中,迭代器极大简化了代码中的循环语句,使代码结构清晰紧凑,然而这些简化了的循环语句实质上隐形地移到了迭代器中。当然用迭代器去处理一个对象时,我们只需提供处理的方法,而不必去关心对象的内部结构,这也解决了对象的使用者与对象内部结构之间的耦合。当然迭代器的存在也为我们提供了操作对象的一个统一接口="" **也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~**="" **好了以上就是本次分享的全部内容,本次示例参考自javascript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。**="" **欢迎转载,转载请注明作者,原文出处。**<="" div="" style="margin: 0px; padding: 0px;">
    好文要顶 关注我 收藏该文  
    东城慕水
    关注 - 10
    粉丝 - 53
    +加关注
    0
    « 上一篇:再起航,我的学习笔记之JavaScript设计模式24(备忘录模式)
posted @ 2017-09-25 11:43 东城慕水 阅读(71) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
发表评论

昵称:

评论内容:
引用 粗体 链接 缩进 代码 图片

 退出 订阅评论

[Ctrl+Enter快捷键提交]

【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
【推荐】腾讯云上实验室 1小时搭建人工智能应用
【推荐】可嵌入您系统的“在线Excel”!SpreadJS 纯前端表格控件
【推荐】阿里云“全民云计算”优惠升级
美团云0921
最新IT新闻:
· 京东要投资中超球队延边?回应:没有投资足球的计划
· 阿里市值距亚马逊仅80亿美元 月初差距还高达373亿美元
· 中国联通成立大数据公司 或与BAT合作更紧密
· 三星可折叠手机“Galaxy X”获韩国监管部门认证
· Office 365 Excel调查改为Forms for Excel
» 更多新闻...
极光0908
最新知识库文章:
· 如何阅读计算机科学类的书
· Google 及其云智慧
· 做到这一点,你也可以成为优秀的程序员
· 写给立志做码农的大学生
· 架构腐化之谜
» 更多知识库文章...
阅读全文
0 0
原创粉丝点击