您好,欢迎访问一九零五行业门户网

消除if else, 让你的代码看起来更优雅

javascript栏目介绍如何消除if else, 让你的代码看起来更优雅,一起来看看吧。前言
应该有不少同学有遇到过充斥着if else的代码,面对这样的一团乱麻,简单粗暴地继续增量修改常常只会让复杂度越来越高,可读性越来越差。那么是时候重构了,花几分钟看看这篇文章, 说不定对你有一丢丢帮助。
场景一: 根据status显示对应名称
优化方案1:object对象
const statusstr = { '1': '待付款', '2': '待发货', '3': '已发货', '4': '交易完成', '5': '交易关闭', 'default': '',}const getstatus = (status) =>{ return statusstr[status] || statusstr['default']}
将判断条件作为对象的属性名,将处理逻辑作为对象的属性值,在按钮点击的时候,通过对象属性查找的方式来进行逻辑判断.
优化方案2: map对象
const statusstr = new map([ '1': ['待付款'], '2': ['待发货'], '3': ['已发货'], '4': ['交易完成'], '5': ['交易关闭'], 'default': [''],])const getstatus = (status) =>{ let actions = statusstr.get(status) || statusstr.get('default') return actions[0];}
这样写用到了es6里的map对象,那么map对象和object对象有什么区别呢?
一个对象通常都有自己的原型,所以一个对象总有一个"prototype"键。一个对象的键只能是字符串或者symbols,但一个map的键可以是任意值。你可以通过size属性很容易地得到一个map的键值对个数,而对象的键值对个数只能手动确认。
场景二:多个condition对应名称
现在把问题升级一下, 以前按钮点击时候只需要判断status,现在还需要判断用户的身份:
「举个栗子:」
const onbuttonclick = (status,identity)=>{ if(identity == 'guest'){ if(status == 1){ //do sth }else if(status == 2){ //do sth }else if(status == 3){ //do sth }else if(status == 4){ //do sth }else if(status == 5){ //do sth }else { //do sth } }else if(identity == 'master') { if(status == 1){ //do sth }else if(status == 2){ //do sth }else if(status == 3){ //do sth }else if(status == 4){ //do sth }else if(status == 5){ //do sth }else { //do sth } }}
上面的例子我们可以看到,当你的逻辑升级为二元判断时,你的判断量会加倍,你的代码量也会加倍,这时怎么写更清爽呢?
优化方案1: 将condition用字符拼接形式存在map对象里
const actions = new map([ ['guest_1', ()=>{/*do sth*/}], ['guest_2', ()=>{/*do sth*/}], ['guest_3', ()=>{/*do sth*/}], ['guest_4', ()=>{/*do sth*/}], ['guest_5', ()=>{/*do sth*/}], ['master_1', ()=>{/*do sth*/}], ['master_2', ()=>{/*do sth*/}], ['master_3', ()=>{/*do sth*/}], ['master_4', ()=>{/*do sth*/}], ['master_5', ()=>{/*do sth*/}], ['default', ()=>{/*do sth*/}],])const onbuttonclick = (identity,status)=>{ let action = actions.get(`${identity}_${status}`) || actions.get('default') action.call(this)}
上述代码核心逻辑是:把两个条件拼接成字符串,并通过以条件拼接字符串作为键,以处理函数作为值的map对象进行查找并执行,这种写法在多元条件判断时候尤其好用。
优化方案2: 将condition用字符拼接形式存在object对象里
const actions = { 'guest_1':()=>{/*do sth*/}, 'guest_2':()=>{/*do sth*/}, //....}const onbuttonclick = (identity,status)=>{ let action = actions[`${identity}_${status}`] || actions['default'] action.call(this)}
优化方案3: 将condition用object对象形式存在map对象里
可能用查询条件拼成字符串有点别扭,那还有一种方案,就是用map对象,以object对象作为key:
const actions = new map([ [{identity:'guest',status:1},()=>{/*do sth*/}], [{identity:'guest',status:2},()=>{/*do sth*/}], //...])const onbuttonclick = (identity,status)=>{ let action = [...actions].filter(([key,value])=>(key.identity == identity && key.status == status)) action.foreach(([key,value])=>value.call(this))}
场景三:根据status做出相应操作
「举个栗子:」
function init () { if (isanswer === 1) { if (isolduser === 1) { // ... } else if (isolduser === 2) { // ... } } else if (isanswer === 2) { if (isolduser === 1) { // ... } else if (isolduser === 2) { // ... } } else if (isanswer === 3) { if (isolduser === 1) { // ... } else if (isolduser === 2) { // ... } }}
优化方案1: 查找表,职责链查找表
const rules = [ { match (an, old) {if (an === 1) {return true}}, action (an, old) { if (old === 1) {// ...} else if (old === 2) {// ...} } }, { match (an, old) { if (an === 2) {return true } }, action (an, old) { if (old === 1) {// ...} else if (old === 2) {// ...} } }, { match (an, old) {if (an === 3) {return true}}, action (an, old) { if (old === 1) {// ...} else if (old === 2) {// ...} } }]function init (an, old) { for (let i = 0; i < rules.length; i++) { // 如果返回true if (rules[i].match(an, old)) { rules[i].action(an, old) } }}init(isanswer, isolduser)
虽然可能看着是治标不治本,其实不然,init函数的复杂度大大的降低了。我们已经把控制流程的复杂逻辑,拆分到determineaction函数中
优化方案2: 函数式编程
import r from 'ramda'var fn = r.cond([ [r.equals(0), r.always('water freezes at 0°c')], [r.equals(100), r.always('water boils at 100°c')], [r.t, temp => 'nothing special happens at ' + temp + '°c']]);fn(0); //=> 'water freezes at 0°c'fn(50); //=> 'nothing special happens at 50°c'fn(100); //=> 'water boils at 100°c'
场景四: 根据范围去进行不同处理
「举个栗子:」比如大家可能会遇到类似下面的需求:比如某平台的信用分数评级,超过700-950,就是信用极好,650-700信用优秀,600-650信用良好,550-600信用中等,350-550信用较差。
function showgrace(grace) { let _level=''; if(grace>=700){ _level='信用极好' } else if(grace>=650){ _level='信用优秀' } else if(grace>=600){ _level='信用良好' } else if(grace>=550){ _level='信用中等' } else{ _level='信用较差' } return _level;}
优化方案1: 用look-up表,把配置数据和业务逻辑分离
function showgrace(grace,level,levelforgrace) { for(let i=0;i<level.length;i++){ if(grace>=level[i]){ return levelforgrace[i]; } } //如果不存在,那么就是分数很低,返回最后一个 return levelforgrace[levelforgrace.length-1];}let graceforlevel=[700,650,600,550];let leveltext=['信用极好','信用优秀','信用良好','信用中等','信用较差'];
小结
很多情况下我们都可以使用更灵活的方式去替代if else以及switch, 但也不是所有的if else都需要替代, 视情况而定。
更多相关免费学习:javascript(视频)
以上就是消除if else, 让你的代码看起来更优雅的详细内容。
其它类似信息

推荐信息