Clean up your code by removing ‘if-else’ statements
Some tips to make your JavaScript code more elegant.
When we write JS code, we often encounter the situation of complex logic judgment. Generally, you can use if/else or switch to implement multiple conditional judgment, but there will be a problem: With the increase of logic complexity, if/else and switch in the code will become more and more bloated. This article will take you to try to write more elegant judgment logic.
For example, let’s look at a piece of code:
/**
* Button click event
* @param {number} status
* Activity status: 1 in progress, 2 in failure, 3 out of stock, 4 in success, 5 system cancelled
*/
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 in the code: Do two things according to the different activity state, send the log buried point and jump to the corresponding page, you can easily come up with a rewrite of this code by switch appearance.
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, it looks much clearer than if/else, careful readers may have also found a small trick: case 2 and case 3’s logic is the same, we can save the execution statement and break, case 2 will automatically execute with case 3’s logic.
But there’s a simpler way to write it.
const actions = {
‘1’: [‘processing’,‘IndexPage’],
‘2’: [‘fail’,‘FailPage’],
‘3’: [‘fail’,‘FailPage’],
‘4’: [‘success’,‘SuccessPage’],
‘5’: [‘cancel’,‘CancelPage’],
‘default’: [‘other’,‘Index’],
}
const onButtonClick = (status)=>{
let action = actions[status] || actions[‘default’],
logName = action[0],
pageName = action[1]
sendLog(logName)
jumpTo(pageName) }
The code above does look cleaner, and the clever thing about this approach is that it uses the judgment condition as the object’s property name, and the processing logic as the object’s property value. When the button is clicked, this method is especially suitable for the case of unary condition judgment, which makes logical judgment by means of object attribute lookup.
It’s fine, but is there another way to code?
Yes!
const actions = new Map([
[1, [‘processing’,‘IndexPage’]],
[2, [‘fail’,‘FailPage’]],
[3, [‘fail’,‘FailPage’]],
[4, [‘success’,‘SuccessPage’]],
[5, [‘cancel’,‘CancelPage’]],
[‘default’, [‘other’,‘Index’]]
])
const onButtonClick = (status)=>{
let action = actions.get(status) || actions.get(‘default’)
sendLog(action[0])
jumpTo(action[1]) }
There are many advantages to using Map instead of Object, which we will talk about later.
What’s the difference between a Map object and a normal object?
- An object usually has its own prototype, so an object always has a “prototype” key
- An object’s key can only be a string or Symbols, but a Map’s key can be any value
- You can easily get the number of key-value pairs in a Map by using the size attribute, whereas the number of key-value pairs in an object can only be confirmed manually
Now let’s upgrade the difficulty of the problem. When clicking the button, you need to judge not only the status but also the user’s identity:
/**
* Button click event
* @param {number} status
* Activity status: 1 in progress, 2 in failure, 3 out of stock, 4 in success, 5 system cancelled
*
* @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
}
} }
As you can see from the example above when your logic escalates to double judgment, your judgment doubles, and your code doubles.
How can we code more cleanly?
Here is a solution:
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) }
The core logic of the above code is: Two judgment conditions are spliced into a string to serve as the key of Map, and then the value corresponding to the corresponding string is directly searched during query.
Of course, we can also change Map to Object here:
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 readers find it a bit awkward to spell out the query as a string, there is another solution, which is to use a Map object as the key:
You can also see the difference between a Map and an Object, where a Map can use any type of data as a key.
Let’s make it a little harder now. What if the status1–4 processing logic is the same in the guest case?
And the worst-case scenario 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 approach would be to cache the processing logic functions:
This is enough for daily needs, but seriously, it’s still a bit annoying to have function A overwritten four times.
If things get really complicated, like identity has 3 states and status has 10 states, you need to define 30 processing logic, many of which are the same, which seems to unacceptable.
And you can do this:
The advantage of using Map instead of Object is more obvious because Regular type can be used as a key.
If the requirement becomes: all guest cases need to send a log buried point, and different status cases need separate logical processing, then we can write as follows:
That is to say, with the property of the array loop, any logic that meets the regular condition will be executed, so that both public logic and individual logic can be executed at the same time.
Conclusion
This article has taught you eight ways to write logical judgments, including:
- if/else
- switch
- Unary judgment: stored in Object
- Unary judgment: save to Map
- Multiple judgment: concatenate the condition into a string and save it in Object
- Multiple judgment: concatenate the condition into a string and store it in a Map
- Multiple judgment: save condition as an object in Map
- Multiple judgment: save condition as a regular expression in Map
So much for this article, and may the future of your life be filled with more than just if/else or switch.
Clean up your code by removing ‘if-else’ statements
Pages: 1 2