假設看到了這樣的代碼,你是否一口老血噴在屏幕上?現在的問題是,面對如此代碼,這麼複雜的邏輯,能否優化?
- if (a && d || b && c && !d || (!a || !b) && c) {
- console.log('pass')
- } else {
- console.log('fail')
- }
你是否一口老血噴在屏幕上?
當然,這段代碼是我參考一個掘金沸點(@隔壁村的李二狗)僞造的,但願你和你的同事都別這麼寫。
能寫出這種與或非,如果不是邏輯不清,那麼估計只有一種可能,需求變更很多次,多人修改後的結果。。
現在的問題是,面對如此代碼,這麼複雜的邏輯,能否優化?
答案是肯定的!
這種問題的探究來自於一門數學:布爾代數或邏輯代數。
說到布爾,我們開發者對此太熟悉了。不就是 true 和 false 嘛。
布爾代數這門課,大學裏應該或多或少都講些吧。因爲我是數學專業畢業的,看到這種問題必須記錄一下,也順便複習一下。
爲了方便表達,JS 中的與或非,我用布爾代數裏面的表示方法:
因此 a && d || b && c && !d || (!a || !b) && c 可以表達爲:
轉化後優先級清晰多了。
現在的問題是,我們如何化簡這個邏輯表達式。
還好有一些常用結論可供我們使用:
前四個公式很好理解。比如,自己或上自己否,當然爲 true。
關鍵在於第 5 個公式沒那麼直觀,可以通過畫圖簡單說明下(其他公式都可以類似推導)。
首先看部分,如圖中綠色區域:
再看,如圖中綠色區域:
則二者之和爲:
而部分正是圖中粉色區域:
因爲粉色區域原本就在前二者之和裏面,因此加多少次都是一樣的。
注意最後這個公式核心特點:和是以和出現的。
有了這幾個公式作爲鋪墊,我們就可以正式推導了(原沸點配圖中有):
根據第 4 條,替換最後一項:
注意到前兩項分別有和,符合第 5 條:
此時最後兩項,符合第 2 條:
最後兩項,其中一項爲,另外一項也包含,滿足第 3 條:
至此化簡完了。真是不可以思議,B 沒了!
此時開篇的代碼簡化成了這樣:
- if (a && d || c) {
- console.log('pass')
- } else {
- console.log('fail')
- }
真清爽。
感謝你看到這裏,希望有所幫助。