在前端的平常開發中,根據不一樣條件執行不一樣的代碼邏輯是最多見不過的,而咱們最經常使用的邏輯也就是if,else了。當咱們的條件變得愈來愈複雜的時候,咱們會發現代碼會出現下面的幾種狀況,讓咱們後續維護工做以及拓展變得愈加困難。javascript
備註:本文並非說全部的if,else的語句都有必要優化,而是指對後續開發以及維護已經形成困擾,或者代碼不嚴謹的風險增大時,咱們能夠考慮的一個方向。前端
特別說明:本文參考了掘金至今爲止發佈的全部有關if/else的文章,也是但願你們在學習瞭解一些知識時儘可能全面的分析某個知識點,判斷原來的場景,以及這種代碼技巧究竟好在哪裏,我爲何要用。java
// 狀況一 :多種判斷臨界值
if(a === 1){
code xxx
} else if(a>==2 && a<==10){
code xxx
} else if(a>==11){
code xxx
}
// 狀況二 :嵌套結構
if(age>18){
if(money>==1000){
}else{
}
} else if(age <== 10){
if(money>==1000){
}else{
}
}
//狀況三 :由於參與條件的不一樣值狀況,
//好比下面這種2個參數,布爾型2個值,那麼組合起來便有4種,若是每一個都不一樣,你最少要寫4個語句塊
if(a && b){
}else if(!a && b){
}else if(a && !b){
}else{
}
//狀況四 :是針對函數而言的,最近比較流行的寫法,當知足返回條件時,儘早返回
if(case 1){
code xxx;
return
}
if(case 2){
code xxx;
return
}
if(case 3){
code xxx;
return
}
複製代碼
之因此列出上面幾種場景,是爲了下面可以更加深刻的針對不一樣狀況列出針對性更強的解決方案。算法
在不少有過一點經驗的前端那裏,咱們能夠常常看到一些代碼技巧,而這些代碼技巧在條件語句優化時一樣適用。編程
switch case大概是咱們最容易想到的優化的方式之一,並且沒有理解成本和使用成本,限制就是對case比較限定,須要根據一個關鍵的值切換策略,而不能是多個值,因此若是你想switch達到比較好的效果,可能有兩種前提:1你的限定條件原本就是一個關鍵值 2 就是你在決定switch的時候,已經把多個值的判斷轉換成了一個值(至於如何轉換下面一條就能夠看到了)。設計模式
//這裏須要提醒給你們的是
// case中能夠寫條件判斷
let a =1
switch(true){
case a<10:{
console.log(0);
break;
}
case a === 10:{
console.log(10);
break;
}
}
// 多個case能夠執行同一個代碼段
switch (a){
case 2:case4:{
}
default:{
}
}
// 若是不寫break,會執行的代碼段1,555會分別打印出來,
//也就是從第一個符合條件的開始,不斷執行邏輯,除非後續遇到break,你須要注意這個盲點,也能夠某種狀況下利用
let a = 10;
switch(a){
case 3:{console.log(4444)}
case 10:{console.log(1);}
case 2:{console.log(555);break}
default:{console.log(a);}
}
複製代碼
在上面的邏輯中,咱們能夠看到有大量的針對關鍵條件進行邏輯判斷的代碼,那麼首先,對於不一樣條件下的代碼段而言, 你只是須要一個判斷的結果,而後執行某段代碼。從這個出發點來講,咱們能夠將全部的判斷語句定義爲函數,這個函數的做用就是經過輸入條件,返回一個能夠決定使用何種方案,執行什麼代碼的惟一值。數組
咱們拿上面的第三種狀況舉例,實際咱們改寫後是這樣的:數據結構
//你能夠將全部的參數收集,綜合寫一個判斷,返回使用哪一種代碼的惟一標識
const judgeStragety = (a,b){
if(a && b){
return 'case1'
}else if(!a && b){
return 'case2'
}else if(a && !b){
return 'case3'
}else{
return 'case4'
}
}
//執行代碼中,你的使用便成了,而後執行對應策略標識的代碼段即可以
let stragety = judgeStragety(a,b)
// 甚至有些狀況下 你以爲某些判斷條件都是不一樣的,你甚至能夠依據某個判斷條件抽離單獨的函數
// 這樣的好處即是,更解耦,
//別人也更能經過你的函數名,判斷出這個邏輯語句的真正價值,否則 q === 1這種,真的別人看不懂
if(judgeA(a,b,c)){
}
if(judgeB(b,f)){
}
複製代碼
函數化編程是前端的基本思惟之一,函數做爲編程的一等公民,咱們時刻要記得針對冗餘、具備優化空間的代碼進行封裝。函數
好比我今天看到某些人代碼寫成這樣,明顯的代碼冗餘,既然代碼具備共同邏輯,就該把這部分抽離爲一個函數,後續也可讓代碼可維護性更強。學習
if(a === 1){
console.log(1111)
alert(10)
}else if(a === 2){
console.log(2222)
alert(20)
}else{
code xxx
}
const action = code=>{
console.log(1111*code)
alert(10*code)
}
if(a===1){
action(1)
}else if(a===2){
action(2)
}else {
code xxx
}
複製代碼
這個部分在我另一篇文章奇技淫巧中有很是詳細的技巧描述,能夠點擊查看:www.yuque.com/robinson/js…
好比:邏輯與執行函數, a && b && fn(),代替 if(a && b){fn()}
好比邏輯或,進行默認賦值 ,let msg = error.msg || '默認展現信息'
三目判斷也是減小條件判斷的一種,由於其經過賦值語句的方式已經將條件不一樣時,兩個處理結果分別給出。
let desc = age > 18 ? '成年人' :'未成年'
針對一些經常使用的數據結構,有不少能夠用來簡化咱們的常見的邏輯語句以及代碼執行策略。
// 原來
if(sex === 0){
desc = '女'
}else if(sex === 1){
desc = '男'
}else{
desc = ''
}
// 使用字典來作1對1 的對應關係
let sexDict = {
0:'女',
1:'男'
}
let desc = sexDict[sex]
// 使用數組收集多個條件值
//原來
if(a === 0 || a ===4){
code xxx
}
// 如今
const statusArr = [0,4]
if(statusArr.includes(status)){
}
//使用map收集複雜值 map的價值就在於能夠設置key爲正則、對象等等
let vaildScore = 'score_2'
let scoreHandler = new Map()
scoreHandler.set(/^score_[1-9]{1}/,()=>console.log('vip1'))
scoreHandler.set(/^score_0/,()=>console.log('vip0'))
scoreHandler.forEach(function(value,key){
if(key.test(vaildScore)){
value()
return
}
})
複製代碼
針對不一樣條件,利用不用算法,得出一個結論。語雀連接:www.yuque.com/robinson/de…
const PriceStrategy = function(){
// 內部算法對象
const stragtegy = {
return30:function(price){
},
return60:function(price){
},
}
// 策略算法調用接口
return function(cheaperLevel,price){
return stragtegy[cheaperLevel] && stragtegy[cheaperLevel](price)
}
}
// 使用方式
let price = PriceStrategy('return30','321.56')
console.log(price)
複製代碼
針對不一樣條件,能夠化解爲各類狀態,執行不一樣狀態的封裝函數,狀態模式地址:www.yuque.com/robinson/de…
let status = light.status
switch(status){
case 'on':console.log('light is on ,we can read books');
break;
case 'off':console.log('light is off ,we can not see anything');
break;
case 'error':console.log('light is error ,we can not do any operation');
break;
}
function lightTip(status){
case 'on':console.log('light is on ,we can read books');
break;
case 'off':console.log('light is off ,we can not see anything');
break;
case 'error':console.log('light is error ,we can not do any operation');
break;
}
// 獲取狀態執行操做
let status = light.status
lightTip(status)
// 其餘邏輯裏更改狀態執行
light.status = 'off'
// 繼續執行
let status = light.status
lightTip(status)
//思考抽象爲電燈狀態
// 電燈類
class light{
setState(state){
this.state = state
}
getState(){
return this.state.status
}
request(){
return this.state.handler()
}
}
// 狀態類
class lightState{
constructor(){
this.status = ''
}
handler(context){
console.error('不在任何有效狀態')
}
}
// 具體狀態實現 啓動狀態
class onState extends lightState{
constructor(){
super();
this.status='on'
}
handler(){
console.log('light is on ,we can read books')
}
}
// 關閉狀態實現
class offState extends lightState{
constructor(){
super();
this.status='off'
}
handler(){
console.log('light is off ,we can not see anything')
}
}
let lightDemo = new light()
lightDemo.setState(new onState())
lightDemo.request()
lightDemo.setState(new offState())
lightDemo.request()
複製代碼
定義n種判斷條件以及執行函數,當不肯定具體執行哪一種時,循環判斷全部隊列中是否有符合條件的可用函數,優勢,靈活方便,能夠靈活的追加或者減小函數;缺點,增長了沒必要要的函數運行成本,不能儘早返回。
let dutyArr = []
dutyArr.push({
match:(a,b)=>{
},
action:()=>{
}
})
dutyArr.push({
match:(a,b)=>{
},
action:()=>{
}
})
dutyArr.forEach(function(item){
if(item.natch(ab)){
item.action()
}
})
複製代碼
管中窺豹,可見一斑。咱們學習編程,要善於從一個點出發,思考各個可能,各類使用場景,適合使用什麼技巧,而非是見一個知道一個用一個。
本文提供的是從小到大,從初級到高級,咱們在處理代碼邏輯時的通用思惟方式,本文所整理的思路也不是最完整、最權威的,只是幫助你們在相應一個技術主題的時候可以像更系統或者更具體的方式多探索一些。
個人js語雀小冊:www.yuque.com/robinson/js…