Home  >  Article  >  Web Front-end  >  Elegant way to write complex judgments in JavaScript

Elegant way to write complex judgments in JavaScript

coldplay.xixi
coldplay.xixiforward
2020-06-16 16:54:012532browse

Elegant way to write complex judgments in JavaScript

Premise

We often encounter complex logical judgments when writing js code. Usually you can use if/else or switch to implement multiple conditional judgments, but There will be a problem with this. As the logic complexity increases, the if/else/switch in the code will become more and more bloated and difficult to understand. So how to write judgment logic more elegantly? This article will give you a try one time.

For example

Look at a piece of code first

/**
 * 按钮点击事件
 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消
 */const onButtonClick = (status)=>{  if(status == 1){
    sendLog('processing')
    jumpTo('IndexPage')
  }else if(status == 2){
    sendLog('fail')
    jumpTo('FailPage')
  }else if(status == 3){
    sendLog('fail')
    jumpTo('FailPage')
  }else if(status == 4){
    sendLog('success')
    jumpTo('SuccessPage')
  }else if(status == 5){
    sendLog('cancel')
    jumpTo('CancelPage')
  }else {
    sendLog('other')
    jumpTo('Index')
  }
}复制代码

You can see the click logic of this button through the code: do two things according to different activity states, send logs to bury points and jump to the corresponding page. You can easily propose a rewriting plan for this code. The switch appears:

/**
 * 按钮点击事件
 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消
 */const onButtonClick = (status)=>{  switch (status){    case 1:
      sendLog('processing')
      jumpTo('IndexPage')      break
    case 2:    case 3:
      sendLog('fail')
      jumpTo('FailPage')      break  
    case 4:
      sendLog('success')
      jumpTo('SuccessPage')      break
    case 5:
      sendLog('cancel')
      jumpTo('CancelPage')      break
    default:
      sendLog('other')
      jumpTo('Index')      break
  }
}复制代码

Well, this looks much clearer than if/else. Careful students also discovered the small Tip, when the logic of case 2 and case 3 is the same, you can omit the execution statement and break, and the logic of case 3 will be automatically executed in case 2.

At this time, some students will say that there is a simpler way to write:

const actions = {  '1': ['processing','IndexPage'],  '2': ['fail','FailPage'],  '3': ['fail','FailPage'],  '4': ['success','SuccessPage'],  '5': ['cancel','CancelPage'],  'default': ['other','Index'],
}/**
 * 按钮点击事件
 * @param {number} status 活动状态:1开团进行中 2开团失败 3 商品售罄 4 开团成功 5 系统取消
 */const onButtonClick = (status)=>{  let action = actions[status] || actions['default'],
      logName = action[0],
      pageName = action[1]
  sendLog(logName)
  jumpTo(pageName)
}复制代码

The above code does look cleaner. The smart thing about this method is that it takes the judgment condition as an object The attribute name uses the processing logic as the attribute value of the object. When the button is clicked, logical judgment is made by searching the object attributes. This writing method is particularly suitable for unary conditional judgment.

Is there any other way to write it? Some:

const actions = new Map([
  [1, ['processing','IndexPage']],
  [2, ['fail','FailPage']],
  [3, ['fail','FailPage']],
  [4, ['success','SuccessPage']],
  [5, ['cancel','CancelPage']],
  ['default', ['other','Index']]
])/**
 * 按钮点击事件
 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消
 */const onButtonClick = (status)=>{  let action = actions.get(status) || actions.get('default')
  sendLog(action[0])
  jumpTo(action[1])
}复制代码

Writing like this uses the Map object in es6. Isn’t it more fun? What is the difference between Map object and Object object?

  1. An object usually has its own prototype, so an object always has a "prototype" key.
  2. The key of an object can only be a string or Symbols, but the key of a Map can be any value.
  3. You can easily get the number of key-value pairs of a Map through the size attribute, while the number of key-value pairs of an object can only be confirmed manually.

We need to upgrade the problem. In the past, we only needed to judge the status when clicking the button. Now we also need to judge the user’s identity:

/**
 * 按钮点击事件
 * @param {number} status 活动状态:1开团进行中 2开团失败 3 开团成功 4 商品售罄 5 有库存未开团
 * @param {string} identity 身份标识:guest客态 master主态
 */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
    }
  }
}复制代码

Forgive me for not writing the specific details of each judgment. Logic, because the code is too verbose.

Forgive me for using if/else again, because I see many people still using if/else to write such large sections of logical judgment.

We can see from the above example that when your logic is upgraded to binary judgment, your judgment amount will double, and your code amount will also double. How to write more refreshingly at this time?

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*/}],
])/**
 * 按钮点击事件
 * @param {string} identity 身份标识:guest客态 master主态
 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 开团成功 4 商品售罄 5 有库存未开团
 */const onButtonClick = (identity,status)=>{  let action = actions.get(`${identity}_${status}`) || actions.get('default')
  action.call(this)
}复制代码

The core logic of the above code is: splice the two conditions into a string, and search and execute the Map object using the conditional string as the key and the processing function as the value. This writing method is used in multiple It is especially useful when making conditional judgments.

Of course, the above code is similar if it is implemented using Object objects:

const actions = {  'guest_1':()=>{/*do sth*/},  'guest_2':()=>{/*do sth*/},  //....}const onButtonClick = (identity,status)=>{  let action = actions[`${identity}_${status}`] || actions['default']
  action.call(this)
}复制代码

If some students feel that it is a bit awkward to spell the query conditions into strings, then there is another solution, which is to use Map objects. , using the Object object as the 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))
}复制代码

Is it a little more advanced?

The difference between Map and Object can also be seen here. Map can use any type of data as key.

Now we will upgrade the difficulty a little bit. What if the processing logic of status1-4 is the same in the guest case. The worst case is this:

const actions = new Map([
  [{identity:'guest',status:1},()=>{/* functionA */}],
  [{identity:'guest',status:2},()=>{/* functionA */}],
  [{identity:'guest',status:3},()=>{/* functionA */}],
  [{identity:'guest',status:4},()=>{/* functionA */}],
  [{identity:'guest',status:5},()=>{/* functionB */}],  //...])复制代码

A better way to write it is Cache the processing logic function:

const actions = ()=>{  const functionA = ()=>{/*do sth*/}  const functionB = ()=>{/*do sth*/}  return new Map([
    [{identity:'guest',status:1},functionA],
    [{identity:'guest',status:2},functionA],
    [{identity:'guest',status:3},functionA],
    [{identity:'guest',status:4},functionA],
    [{identity:'guest',status:5},functionB],    //...
  ])
}const onButtonClick = (identity,status)=>{  let action = [...actions()].filter(([key,value])=>(key.identity == identity && key.status == status))
  action.forEach(([key,value])=>value.call(this))
}复制代码

Writing like this can already meet daily needs, but to be serious, it is still a bit uncomfortable to rewrite functionA 4 times above. If the judgment condition becomes particularly complicated, for example, identity has There are 3 states, and status has 10 states. Then you need to define 30 processing logics, and often many of these logics are the same. This seems to be something I don’t want to accept. It can be implemented like this:

const actions = ()=>{  const functionA = ()=>{/*do sth*/}  const functionB = ()=>{/*do sth*/}  return new Map([
    [/^guest_[1-4]$/,functionA],
    [/^guest_5$/,functionB],    //...
  ])
}const onButtonClick = (identity,status)=>{  let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`)))
  action.forEach(([key,value])=>value.call(this))
}复制代码

The advantages of Map are more prominent here. Regular types can be used as keys, which opens up unlimited possibilities. If the demand changes, a log burying point must be sent for all guest situations, and different status situations also require separate logical processing, then we You can write it like this:

const actions = ()=>{  const functionA = ()=>{/*do sth*/}  const functionB = ()=>{/*do sth*/}  const functionC = ()=>{/*send log*/}  return new Map([
    [/^guest_[1-4]$/,functionA],
    [/^guest_5$/,functionB],
    [/^guest_.*$/,functionC],    //...
  ])
}const onButtonClick = (identity,status)=>{  let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`)))
  action.forEach(([key,value])=>value.call(this))
}复制代码

That is to say, using the characteristics of array loops, logic that meets the regular conditions will be executed. Then you can execute public logic and individual logic at the same time. Because of the existence of regular rules, you can open up your imagination. To unlock more ways to play, I won’t go into details in this article.

Summary

This article has taught you 8 ways to write logical judgments, including:

  1. if/else
  2. switch
  3. When making one-yuan judgment: Save it in Object
  4. When making one-way judgment: Save it in Map
  5. When making multiple judgments: Splice the condition into a string and save it in Object
  6. Multiple When judging: Splice the condition into a string and save it in the Map
  7. When judging multiple variables: Save the condition as an Object and save it in the Map
  8. When judging multiple variables: Write the condition as a regular expression and save it in the Map

At this point, this article will come to an end. I hope your future life will not only have if/else/switch.

If you are interested in this article, please follow the author's WeChat public account: "大 Zhuan Zhuan Fe"

Recommended tutorial: "JavaScriptBasic Tutorial

The above is the detailed content of Elegant way to write complex judgments in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.im. If there is any infringement, please contact admin@php.cn delete