如何使用迭代器模式
导读:本文共3085.5字符,通常情况下阅读需要10分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要:你将学到迭代器模式的含义实现一个数组迭代器实现一个对象迭代器实现路径查找/赋值迭代器如何用迭代器的思想解决分支循环嵌套问题实现一个图片播放器正文1.迭代器的含义迭代器模式主要的思想就是在不暴露对象内部结构的同时可以按照一定顺序访问对象内部的元素。其实javascript中的很多方法都运用了迭代器的思想,比如数组的forEach,every,find,some,map,entries等等,这些操作极... ...
目录
(为您整理了一些要点),点击可以直达。你将学到
迭代器模式的含义
实现一个数组迭代器
实现一个对象迭代器
实现路径查找/赋值迭代器
如何用迭代器的思想解决分支循环嵌套问题
实现一个图片播放器
正文
1.迭代器的含义
迭代器模式主要的思想就是在不暴露对象内部结构的同时可以按照一定顺序访问对象内部的元素。
其实javascript中的很多方法都运用了迭代器的思想,比如数组的forEach,every,find,some,map,entries等等,这些操作极大的简化了我们的逻辑操作,接下来我们就来看看它的具体应用吧。
2.实现一个数组迭代器
我们都知道javascript中数组的forEach方法,那么不用这个方法,我们能自己实现一个吗?
//数组迭代器leteachArr=function(arr,fn){leti=0,len=arr.length;for(;i<len;i++){if(fn.call(arr[i],i,arr[i])===false){break;}}}//使用eachArr([1,2,3,4],(index,value)=>{console.log(index,value)})
3.实现一个对象迭代器
对象迭代器和数组迭代器类似, 只是传参不同,如下:
//对象迭代器leteachObj=function(obj,fn){for(letkeyinobj){if(fn.call(obj[key],key,obj[key])===false){break;}}}//使用eachObj({a:11,b:12},(key,value)=>{console.log(key,value)})
4.实现路径查找/赋值迭代器
有时候我们操作对象的某些属性时,我们不知道服务器端是否将该属性或者该属性的上级属性正确的返回给我们,这个时候我们直接通过点语法或者[]语法直接访问会导致代码报错,因此需要我们每一层操作都要做安全校验,这样会产生大量臃肿代码,比如:
letobj={};//获取obj.num.titNumlettitNum=obj.num.titNum;//报错lettitNum=obj&&obj.num&&obj.num.titNum;//正确
我们通过迭代器可以极大的减少这种校验,实现更健壮的代码模式:
letfindObjAttr=function(obj,key){if(!obj||!key){returnundefined}letresult=obj;key=key.split('.');for(leti=0;len=key.length;i<len;i++){if(result[key[i]]!==undefined){result=result[key[i]]}else{returnundefined}}returnresult}//使用leta={b:{c:{d:1}}};findObjAttr(a,'a.b.c.d')//1
这种方式是不是有点类似于lodash的对象/数组查找器呢?同理,我们也可以实现路径赋值器,如下所示:
letsetObjAttr=function(obj,key,value){if(!obj){returnfalse}letresult=obj,key=key.split('.');for(leti=0,len=key.length;i<len-1;i++){if(result[key[i]]===undefined){result[key[i]]={};}if(!(result[key[i]]instanceofObject)){//如果第i层对应的不是一个对象,则剖出错误thrownewError('isnotObject')returnfalse}result=result[key[i]]}returnresult[key[i]]=val}//使用setObjAttr(obj,'a.b.c.d','xuxi')
5.如何用迭代器的思想解决分支循环嵌套问题
分支循环嵌套的问题主要是指在循环体中还需要进行额外的判断,如果判断条件变多,将会造成严重的性能开销问题,如下面的例子:
//数据分组functiongroup(name,num){letdata=[];for(leti=0;i<num;i++){switch(name){case'header':data[i][0]=0;data[i][1]=1;break;case'content':data[i][0]=2;data[i][1]=3;break;case'footer':data[i][0]=4;data[i][1]=532;break;default:break;}}returndata}
由以上分析可知,上面的代码还有很多优化空间,因为每一次遍历都要进行一次分支判断,那么如果num变成100000,且name的种类有100种,那么我们就要做100000*100种无用的分支判断,这样无疑会让你的代码在大数据下卡死。不过我们可以通过以下这种方式优化它:
//数据分组functiongroup(name,num){letdata=[];letstrategy=function(){letdeal={'default':function(i){return},'header':function(i){data[i][0]=0;data[i][1]=1;},'content':function(i){data[i][0]=2;data[i][1]=3;},//...}returnfunction(name){returndeal[name]||deal['default']}}();//迭代器处理数据function_each(fn){for(leti=0;i<num;i++){fn(i)}}_each(strategy(name))returndata}
这样我们就能避免分支判断,极大的提高了代码效率和性能。
6.实现一个图片播放器
图片播放器主要有以上几个功能,上一页,下一页,首页,尾页,自动播放按钮,停止按钮。具体组件的设计机构可以参考我写的demo:
//图片播放器letimgPlayer=function(imgData,box){letcontainer=box&&document.querySelector(box)||document,img=container.querySelector('img'),//获取图片长度len=imgData.length,//当前索引值index=0;//初始化图片img.src=imgData[0];vartimer=null;return{//获取第一个图片first:function(){index=0img.src=imgData[index]},//获取最后一个图片last:function(){index=len-1img.src=imgData[index]},//切换到前一张图片pre:function(){if(--index>0){img.src=imgData[index]}else{index=0img.src=imgData[index]}},//切换到后一张图片next:function(){if(++index<len){img.src=imgData[index]}else{index=len-1img.src=imgData[index]}},//自动播放图片play:function(){timer=setInterval(()=>{if(index>len-1){index=0}img.src=imgData[index]index++},5000)},//停止播放图片stop:function(){clearInterval(timer)}}}//使用letplayer=newimgPlayer(imgData,'#box')
总之,迭代器思想和其他设计模式的组合,可以设计出各种各样高度配置的组件,所以说学好并理解 javascript 设计模式的精髓,决定了我们的高度和态度。
如何使用迭代器模式的详细内容,希望对您有所帮助,信息来源于网络。