作者:Think.
連接:https://juejin.im/post/6844903705058213896
來源:掘金
我們時常寫一些判斷,有時候條件過多會讓代碼看起來很臃腫且不直觀,本文作者整理了一些更優雅的寫法。
輸入分數,依照分數區段輸出等第以及訊息
const getScoreInfo = (score) => {
let level = Math.floor(score / 10)
if (level == 10) {
sendLevel('等第: A')
sendMessage('好強!')
} else if (level == 9) {
sendLevel('等第: B')
sendMessage('繼續保持')
} else if (level == 8) {
sendLevel('等第: B')
sendMessage('繼續保持!')
} else if (level == 7) {
sendLevel('等第: C')
sendMessage('還有進步空間')
} else if (level == 6) {
sendLevel('等第: D')
sendMessage('要再加強')
} else {
sendLevel('等第: F')
sendMessage('加油')
}
}
看起來節省很多,而且80分以上跟90分以上輸出一樣,可以用break
const getScoreInfo = (score) => {
let level = Math.floor(score / 10)
switch (level) {
case 10:
sendLevel('等第: A')
sendMessage('好強!')
break
case 9:
case 8:
sendLevel('等第: B')
sendMessage('繼續保持')
break
case 7:
sendLevel('等第: C')
sendMessage('還有進步空間')
break
case 6:
sendLevel('等第: D')
sendMessage('要再加強')
break
default:
sendLevel('等第: F')
sendMessage('加油')
break
}
}
將判斷條件作為對象的屬性名,將處理邏輯作為對象的屬性值
const getScoreInfo = (score) => {
let level = score / 10
const conditionObj = {
'10': ['等第: A', '好強!'],
'9': ['等第: B', '繼續保持'],
'8': ['等第: B', '繼續保持'],
'7': ['等第: C', '還有進步空間'],
'6': ['等第: D', '要再加強'],
'default': ['等第: F', '加油'],
}
let action = conditionObj[level] || conditionObj['default']
let levelInfo = action[0]
let messageInfo = action[1]
sendLevel(levelInfo)
sendMessage(messageInfo)
}
跟上一個方法很像,只是Map
附註: 跟Object比較有以下優點
- Object的key僅能用字符串或是Symbol對象,但Map可以是任意值
- Map對象有size屬性能輕鬆獲得鍵值對個數
const getScoreInfo = (score) => {
let level = Math.floor(score / 10)
const conditionMap = new Map([
[10, ['等第: A', '好強!']],
[9, ['等第: B', '繼續保持']],
[8, ['等第: B', '繼續保持']],
[7, ['等第: C', '還有進步空間']],
[6, ['等第: D', '要再加強']]
['default', ['等第: F', '加油']]
])
let action = conditionMap[level] || conditionMap['default']
let levelInfo = action[0]
let messageInfo = action[1]
sendLevel(levelInfo)
sendMessage(messageInfo)
}
接下來邏輯判斷變得更複雜,在判斷分數前要先判斷是哪一門科目
const getScoreInfo = (score, subject) => {
let level = Math.floor(score / 10)
if (subject == '國文') {
if (level == 10) {
//do sth
} else if (level == 9) {
//do sth
} else if (level == 8) {
//do sth
} else if (level == 7) {
//do sth
} else if (level == 6) {
//do sth
} else {
//do sth
}
} else if (subject == '數學') {
if (level == 10) {
//do sth
} else if (level == 9) {
//do sth
} else if (level == 8) {
//do sth
} else if (level == 7) {
//do sth
} else if (level == 6) {
//do sth
} else {
//do sth
}
}
}
簡單來說就是拼接 subject 以及 level
const getScoreInfo = (score, subject) => {
let level = Math.floor(score / 10)
const conditionObj = {
// 拼接條件讓它變成一維
'國文_10': () => {/*do sth*/ },
'國文_9': () => {/*do sth*/ },
'國文_8': () => {/*do sth*/ },
'國文_7': () => {/*do sth*/ },
'國文_6': () => {/*do sth*/ },
'國文_default': () => {/*do sth*/ },
'數學_10': () => {/*do sth*/ },
'數學_9': () => {/*do sth*/ },
'數學_8': () => {/*do sth*/ },
'數學_7': () => {/*do sth*/ },
'數學_6': () => {/*do sth*/ },
'數學_default': () => {/*do sth*/ },
}
let action = conditionObj[`${subject}_${level}`] || conditionObj[`${subject}_default`]
action.call(this)
}
其實就是改寫一下conditionObj 變成Map對象
const getScoreInfo = (score, subject) => {
let level = Math.floor(score / 10)
const conditionMap = new Map([
// 拼接條件讓它變成一維
['國文_10', () => {/*do sth*/ }],
['國文_9', () => {/*do sth*/ }],
['國文_8', () => {/*do sth*/ }],
// ...
])
let action = conditionMap[`${subject}_${level}`] || conditionMap[`${subject}_default`]
action.call(this)
}
跟上一題幾乎一樣。
只是把拼接條件變字符串改成對象 (只有Map能這樣,因為Object的key僅用字符串或Symbol)
const getScoreInfo = (score, subject) => {
let level = Math.floor(score / 10)
const conditionMap = new Map([
// 拼接條件讓它變成一維
[{subject: '國文', level: 10}, () => {/*do sth*/ }],
[{subject: '國文', level: 9}, () => {console.log('打印')}],
[{subject: '國文', level: 8}, () => {/*do sth*/ }],
// ...
])
console.log([...conditionMap]);
let action = [...conditionMap].filter(([key, value] /*解構賦值*/) => {
return key.subject == subject && key.level == level
})
console.log(action);
action.forEach(([key, value] /*解構賦值*/ ) => value.call(this))
}
getScoreInfo(95, '國文')
action.forEach(([key, value] /*解構賦值*/ ) => value.call(this))
假設今天某幾個情況輸出結果都一樣
const conditionMap = new Map([
// 拼接條件讓它變成一維
[{subject: '國文', level: 10}, () => { /* functionA */ }],
[{subject: '國文', level: 9}, () => { /* functionA */ }],
[{subject: '國文', level: 8}, () => { /* functionA */ }],
[{subject: '國文', level: 7}, () => { /* functionB */ }],
// ...
])
const conditionMapFn = () => {
const functionA = () => {/*do sth*/ }
const functionB = () => {/*do sth*/ }
return new Map([
[{ subject: '國文', level: 10 }, functionA ],
[{ subject: '國文', level: 9}, functionA ],
[{ subject: '國文', level: 8}, functionA ],
[{ subject: '國文', level: 7 }, functionB ],
//...
])
}
const getScoreInfo = (identity, status) => {
let action = [...conditionMapFn()].filter(([key, value]) => (key.identity == identity && key.status == status))
action.forEach(([key, value]) => value.call(this))
}
缺點:我們發現返回的Map對象要一直寫functionA,假如今天邏輯判斷有超多且很多都是執行相同函數肯定很麻煩,因此我們利用正則優化他。
可以看出Map的key可以設置任何類型真的非常強大
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))
}
作者總結之八種寫邏輯判斷方法 :