如果還想靈活一些,可以封裝一個(gè)稍微通用一點(diǎn)的look-up函數(shù)。
function showGrace(grace,level,levelForGrace) { for(let i=0;i<level.length;i++){ if(grace>=level[i]){ return levelForGrace[i]; } } //如果不存在,那么就是分?jǐn)?shù)很低,返回最后一個(gè) return levelForGrace[levelText.length-1]; } let graceForLevel=[700,650,600,550]; let levelText=['信用極好','信用優(yōu)秀','信用良好','信用中等','信用較差'];
使用推薦配置數(shù)據(jù)和業(yè)務(wù)邏輯分離形式開發(fā),還有一個(gè)好處,在上面例子沒體現(xiàn)出來(lái),下面簡(jiǎn)單說下。比如輸入一個(gè)景點(diǎn),給出景點(diǎn)所在的城市。
function getCityForScenic(scenic) { let _city='' if(scenic==='廣州塔'){ _city='廣州' } else if(scenic==='西湖'){ _city='杭州' } return _city; }
輸入廣州塔,就返回廣州。輸入西湖就返回杭州。但是一個(gè)城市不止一個(gè)景點(diǎn),那么有人習(xí)慣這樣寫。
if(scenic==='廣州塔'||scenic==='花城廣場(chǎng)'||scenic==='白云山'){ _city='廣州' }
如果景點(diǎn)很多,數(shù)據(jù)很長(zhǎng),看著難受,有些人喜歡這樣寫
let scenicOfHangZhou=['西湖','湘湖','砂之船生活廣場(chǎng)','京杭大運(yùn)河','南宋御街'] if(~scenicOfHangZhou.indexOf(scenic)){ _city='杭州' }
這樣執(zhí)行沒錯(cuò),但是寫出來(lái)的代碼可能像下面這樣,風(fēng)格不統(tǒng)一。
function getCityForScenic(scenic) { let _city=''; let scenicOfHangZhou=['西湖','湘湖','砂之船生活廣場(chǎng)','京杭大運(yùn)河','南宋御街']; if(scenic==='廣州塔'||scenic==='花城廣場(chǎng)'||scenic==='白云山'){ _city='廣州' } else if(~scenicOfHangZhou.indexOf(scenic)){ _city='杭州' } return _city; }
即使用switch,也有可能出現(xiàn)這樣的情況
function getCityForScenic(scenic) { let _city=''; let scenicOfHangZhou=['西湖','湘湖','砂之船生活廣場(chǎng)','京杭大運(yùn)河','南宋御街']; switch(true){ case (scenic==='廣州塔'||scenic==='花城廣場(chǎng)'||scenic==='白云山'):_city='廣州';break; case (!!~scenicOfHangZhou.indexOf(scenic)):return '杭州'; } return _city; }
雖然上面的代碼出現(xiàn)的概率很小,但畢竟會(huì)出現(xiàn)。這樣的代碼可能會(huì)造成日后維看得眼花繚亂。如果使用了配置數(shù)據(jù)和業(yè)務(wù)邏輯分離,那就可以避免這個(gè)問題。
function getCityForScenic(scenic) { let cityConfig={ '廣州塔':'廣州', '花城廣場(chǎng)':'廣州', '白云山':'廣州', '西湖':'杭州', '湘湖':'杭州', '京杭大運(yùn)河':'杭州', '砂之船生活廣場(chǎng)':'杭州', '南宋御街':'杭州', } return cityConfig[scenic]; }
function getCityForScenic(scenic) { let cityConfig=[ { scenic:'廣州塔', city:'廣州' }, { scenic:'花城廣場(chǎng)', city:'廣州' }, { scenic:'白云山', city:'廣州' }, { scenic:'西湖', city:'杭州' }, { scenic:'湘湖', city:'杭州' }, { scenic:'京杭大運(yùn)河', city:'杭州' }, { scenic:'砂之船生活廣場(chǎng)', city:'杭州' } ] for(let i=0;i<cityConfig.length;i++){ if(cityConfig[i].scenic===scenic){ return cityConfig[i].city } } }
這樣一來(lái),如果以后要加什么景點(diǎn),對(duì)應(yīng)什么城市,只能修改上面的cityConfig,業(yè)務(wù)邏輯不需要改,也不能改。代碼風(fēng)格上面就做到了統(tǒng)一。
這里簡(jiǎn)單總結(jié)下,使用配置數(shù)據(jù)和業(yè)務(wù)邏輯分離的形式,好處
修改配置數(shù)據(jù)比業(yè)務(wù)邏輯修改成本更小,風(fēng)險(xiǎn)更低
配置數(shù)據(jù)來(lái)源和修改都可以很靈活
配置和業(yè)務(wù)邏輯分離,可以更快的找到需要修改的代碼
配置數(shù)據(jù)和業(yè)務(wù)邏輯可以讓代碼風(fēng)格統(tǒng)一
比如下面這個(gè)根絕傳入時(shí)間戳,顯示評(píng)論時(shí)間顯示的需求,
發(fā)布1小時(shí)以內(nèi)的評(píng)論:x分鐘前
發(fā)布1小時(shí)~24小時(shí)的評(píng)論:x小時(shí)前
發(fā)布24小時(shí)~30天的評(píng)論:x天前
發(fā)布30天以上的評(píng)論:月/日
去年發(fā)布并且超過30天的評(píng)論:年/月/日
實(shí)現(xiàn)不難,幾個(gè)if-else就行了
function formatDate(timeStr){ //獲取當(dāng)前時(shí)間戳 let _now=+new Date(); //求與當(dāng)前的時(shí)間差 let se=_now-timeStr; let _text=''; //去年 if(new Date(timeStr).getFullYear()!==new Date().getFullYear()&&se>2592000000){ _text=new Date(timeStr).getFullYear()+'年'+(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日'; } //30天以上 else if(se>2592000000){ _text=(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日'; } //一天以上 else if(se>86400000){ _text=Math.floor(se/86400000)+'天前'; } //一個(gè)小時(shí)以上 else if(se>3600000){ _text=Math.floor(se/3600000)+'小時(shí)前'; } //一個(gè)小時(shí)以內(nèi) else{ //如果小于1分鐘,就顯示1分鐘前 if(se<60000){se=60000} _text=Math.floor(se/60000)+'分鐘前'; } return _text; }
運(yùn)行結(jié)果沒問題,但是也存在一個(gè)問題,就是這個(gè)需求有神仙數(shù)字:2592000000,86400000,3600000,60000。對(duì)于后面維護(hù)而言,一開始可能并不知道這個(gè)數(shù)字是什么東西。
所以下面就消滅神仙數(shù)字,常量化
function formatDate(timeStr){ //獲取當(dāng)前時(shí)間戳 let _now=+new Date(); //求與當(dāng)前的時(shí)間差 let se=_now-timeStr; const DATE_LEVEL={ month:2592000000, day:86400000, hour:3600000, minter:60000, } let _text=''; //去年 if(new Date(timeStr).getFullYear()!==new Date().getFullYear()&&se>DATE_LEVEL.month){ _text=new Date(timeStr).getFullYear()+'年'+(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日'; } //一個(gè)月以上 else if(se>DATE_LEVEL.month){ _text=(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日'; } //一天以上 else if(se>DATE_LEVEL.day){ _text=Math.floor(se/DATE_LEVEL.day)+'天前'; } //一個(gè)小時(shí)以上 else if(se>DATE_LEVEL.hour){ _text=Math.floor(se/DATE_LEVEL.hour)+'小時(shí)前'; } //一個(gè)小時(shí)以內(nèi) else{ //如果小于1分鐘,就顯示1分鐘前 if(se<DATE_LEVEL.minter){se=DATE_LEVEL.minter} _text=Math.floor(se/DATE_LEVEL.minter)+'分鐘前'; } return _text; }
運(yùn)行結(jié)果也是正確的,代碼多了,但是神仙數(shù)字沒了。可讀性也不差。
這里也順便提一下,如果硬要把上面的需求改成look-up的方式,代碼就是下面這樣。這樣代碼的修改的擴(kuò)展性會(huì)強(qiáng)一些,成本會(huì)小一些,但是可讀性不如上面。取舍關(guān)系,實(shí)際情況,實(shí)際分析。function formatDate(timeStr){ //獲取當(dāng)前時(shí)間戳 let _now=+new Date(); //求與當(dāng)前的時(shí)間差 let se=_now-timeStr; let _text=''; //求上一年最后一秒的時(shí)間戳 let lastYearTime=new Date(new Date().getFullYear()+'-01-01 00:00:00')-1; //把時(shí)間差添加進(jìn)去(當(dāng)前時(shí)間戳與上一年最后一秒的時(shí)間戳的差)添加進(jìn)去,如果時(shí)間差(se)超過這個(gè)值,則代表了這個(gè)時(shí)間是上一年的時(shí)間。 //DATE_LEVEL.unshift(_now-lastYearTime); const DATE_LEVEL={ month:2592000000, day:86400000, hour:3600000, minter:60000, } let handleFn=[ { time:DATE_LEVEL.month, fn:function(timeStr){ return (new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日'; } }, { time:DATE_LEVEL.day, fn:function(timeStr){ return Math.floor(se/DATE_LEVEL.day)+'天前'; } }, { time:DATE_LEVEL.hour, fn:function(timeStr){ return Math.floor(se/DATE_LEVEL.hour)+'小時(shí)前'; } }, { time:DATE_LEVEL.minter, fn:function(timeStr){ return Math.ceil(se/DATE_LEVEL.minter)+'分鐘前'; } } ]; //求上一年最后一秒的時(shí)間戳 let lastYearTime=new Date(new Date().getFullYear()+'-01-01 00:00:00')-1; //把時(shí)間差(當(dāng)前時(shí)間戳與上一年最后一秒的時(shí)間戳的差)和操作函數(shù)添加進(jìn)去,如果時(shí)間差(se)超過這個(gè)值,則代表了這個(gè)時(shí)間是上一年的時(shí)間。 handleFn.unshift({ time:_now-lastYearTime, fn:function(timeStr){ if(se>DATE_LEVEL.month){ return new Date(timeStr).getFullYear()+'年'+(new Date(timeStr).getMonth()+1)+'月'+new Date(timeStr).getDate()+'日'; } }, }); let result=''; for(let i=0;i<handleFn.length;i++){ if(se>=handleFn[i].time){ result=handleFn[i].fn(timeStr); if(result){ return result; } } } //如果發(fā)布時(shí)間小于1分鐘,之際返回1分鐘 return result='1分鐘前' }
比如有一個(gè)需求:傳入cash,check,draft,zfb,wx_pay,對(duì)應(yīng)輸出:現(xiàn)金,支票,匯票,支付寶,微信支付。
需求也很簡(jiǎn)單,就一個(gè)switch就搞定了
function getPayChanne(tag){ switch(tag){ case 'cash':return '現(xiàn)金'; case 'check':return '支票'; case 'draft':return '匯票'; case 'zfb':return '支付寶'; case 'wx_pay':return '微信支付'; } }
但是這個(gè)的硬傷還是和上面一樣,萬(wàn)一下次又要多加一個(gè)如:bank_trans對(duì)應(yīng)輸出銀行轉(zhuǎn)賬呢,代碼又要改。類似的問題,同樣的解決方案,配置數(shù)據(jù)和業(yè)務(wù)邏輯分離。代碼如下。
function getPayChanne(tag){ let payChanneForChinese = { 'cash': '現(xiàn)金', 'check': '支票', 'draft': '匯票', 'zfb': '支付寶', 'wx_pay': '微信支付', }; return payChanneForChinese[tag]; }
同理,如果想封裝一個(gè)通用的,也可以的
let payChanneForChinese = { 'cash': '現(xiàn)金', 'check': '支票', 'draft': '匯票', 'zfb': '支付寶', 'wx_pay': '微信支付', }; function getPayChanne(tag,chineseConfig){ return chineseConfig[tag]; } getPayChanne('cash',payChanneForChinese);
這里使用對(duì)象代替 switch 好處就在于
使用對(duì)象不需要 switch 逐個(gè) case 遍歷判斷。
使用對(duì)象,編寫業(yè)務(wù)邏輯可能更靈活
使用對(duì)象可以使得配置數(shù)據(jù)和業(yè)務(wù)邏輯分離。好處參考上一部分內(nèi)容。
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com