前端(vue)入門到精通課程:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:
【相關推薦:、】
最近在網上衝浪時看到了這樣一段程式碼:
function getUserDescribe(name) {
if (name === "小劉") {
console.log("劉哥哥");
} else if (name === "小紅") {
console.log("小紅妹妹");
} else if (name === "陳龍") {
console.log("大師");
} else if (name === "李龍") {
console.log("師傅");
} else if (name === "大鵬") {
console.log("惡人");
} else {
console.log("此人比較神祕!");
}}
登入後複製
咋一看沒感覺有什麼異常,但如果有1000個判斷條件,按照這種寫法難不成要寫1000個 if
分支?
如果寫了大量的 if
分支,並且可能還具有分支套分支,可以想象到整個程式碼的可讀性和可維護都會大大降低,這在實際開發中,確實是一個比較頭疼的問題,那有沒有什麼辦法能夠即實現需求又能避免這些問題呢?
這就涉及到分支優化,讓我們轉換思維,去優化一下上面的程式碼結構:
function getUserDescribe(name) {
const describeForNameMap = {
小劉: () => console.log("劉哥哥"),
小紅: () => console.log("小紅妹妹"),
陳龍: () => console.log("大師"),
李龍: () => console.log("師傅"),
大鵬: () => console.log("惡人"),
};
describeForNameMap[name] ? describeForNameMap[name]() : console.log("此人比較神祕!");}
登入後複製
問題程式碼中的判斷都是簡單的相等判斷,那麼我們就可以將這些判斷條件作為一個屬性寫到物件describeForNameMap
中去,這些屬性對應的值就是條件成立後的處理常式。
之後我們就只需通過getUserDescribe
函數接收到的引數去獲取describeForNameMap
物件中對應的值,如果該值存在就執行該值(因為值是一個函數)。
這樣一來原本的 if
分支判斷就轉換成了簡單的key value
對應值,條件與處理常式一一對應,一目瞭然。
那如果我們的 if
分支中的判斷條件不只是簡單的相等判斷,還具有一些需要計算的表示式時,我們該怎麼辦呢?(如下所示)
function getUserDescribe(name) {
if (name.length > 3) {
console.log("名字太長");
} else if (name.length < 2) {
console.log("名字太短");
} else if (name[0] === "陳") {
console.log("小陳");
} else if (name[0] === "李" && name !== "李鵬") {
console.log("小李");
} else if (name === "李鵬") {
console.log("管理員");
} else {
console.log("此人比較神祕!");
}}
登入後複製
對於這種結構的程式碼就不能引入物件來進行分支優化了,我們可以引入二維陣列來進行分支優化:
function getUserDescribe(name) {
const describeForNameMap = [
[
(name) => name.length > 3, // 判斷條件
() => console.log("名字太長") // 執行函數
],
[
(name) => name.length < 2,
() => console.log("名字太短")
],
[
(name) => name[0] === "陳",
() => console.log("小陳")
],
[
(name) => name === "大鵬",
() => console.log("管理員")
],
[
(name) => name[0] === "李" && name !== "李鵬",
() => console.log("小李"),
],
];
// 獲取符合條件的子陣列
const getDescribe = describeForNameMap.find((item) => item[0](name));
// 子陣列存在則執行子陣列中的第二個元素(執行函數)
getDescribe ? getDescribe[1]() : console.log("此人比較神祕!");}
登入後複製
上面我們定義了一個describeForNameMap
陣列,陣列內的每一個元素代表一個判斷條件與其執行函數的集合(也是一個陣列),之後我們通過陣列的find
方法查詢describeForNameMap
陣列中符合判斷條件的子陣列即可。
上面例子中我們定義的這個describeForNameMap
物件是一個獨立的結構,我們完全可以將它抽離出去:
const describeForNameMap = {
小劉: () => console.log("劉哥哥"),
小紅: () => console.log("小紅妹妹"),
陳龍: () => console.log("大師"),
李龍: () => console.log("師傅"),
大鵬: () => console.log("惡人"),};function getUserDescribe(name) {
describeForNameMap[name] ? describeForNameMap[name]() : console.log("此人比較神祕!");}
登入後複製
const describeForNameMap = [
[
(name) => name.length > 3, // 判斷條件
() => console.log("名字太長") // 執行函數
],
[
(name) => name.length < 2,
() => console.log("名字太短")
],
[
(name) => name[0] === "陳",
() => console.log("小陳")
],
[
(name) => name === "大鵬",
() => console.log("管理員")
],
[
(name) => name[0] === "李" && name !== "李鵬",
() => console.log("小李"),
],];
function getUserDescribe(name) {
// 獲取符合條件的子陣列
const getDescribe = describeForNameMap.find((item) => item[0](name));
// 子陣列存在則執行子陣列中的第二個元素(執行函數)
getDescribe ? getDescribe[1]() : console.log("此人比較神祕!");}
登入後複製
通過模組化的開發也可以將這個
map
物件寫進一個單獨的js
檔案,之後在需要使用的地方匯入即可。
這樣一來整個getUserDescribe
函數就變得非常簡潔,有的同學可能會問這有什麼用呢?這不是更加麻煩了嗎?如果真的嫌if else
不好看,那我就使用if return
不用else
就好了:
function getUserDescribe(name) {
if (name === "小劉") {
console.log("劉哥哥");
return;
}
if (name === "小紅") {
console.log("小紅妹妹");
return;
}
if (name === "陳龍") {
console.log("大師");
return;
}
if (name === "李龍") {
console.log("師傅");
return;
}
if (name === "大鵬") {
console.log("惡人");
return;
}
console.log("此人比較神祕!");}
登入後複製
試想一下,如果你getUserDescribe
函數中有1000個判斷分支,並且還具有大量的根據判斷結果來執行的處理程式碼,並且getUserDescribe
函數會返回這個處理後的判斷結果的值。
這時getUserDescribe
函數的重點在於對判斷結果的處理,而不在於這個結果是通過什麼分支獲取的,例如:
function getUserDescribe(name) {
let str; // 儲存判斷結果
if (name.length > 3) {
str = "名字太長";
} else if (name.length < 2) {
str = "名字太短";
} else if (name[0] === "陳") {
str = "小陳";
} else if (name[0] === "李" && name !== "李鵬") {
str = "小李";
} else if (name === "李鵬") {
str = "管理員";
} else {
str = "此人比較神祕!";
}
// 對判斷結果str的一些處理
// ......
console.log(str);
return str;}
登入後複製
如果你不進行分支優化,getUserDescribe
函數就會被大量的 if
分支搶佔空間,使得getUserDescribe
函數的重點迷失(getUserDescribe
函數重點在於對判斷結果的處理,而不在於這個結果是通過什麼分支獲取的),這時你再看一下我們優化後的程式碼:
const describeForNameMap = [
[(name) => name.length > 3, () => "名字太長"],
[(name) => name.length < 2, () => "名字太短"],
[(name) => name[0] === "陳", () => "小陳"],
[(name) => name === "大鵬", () => "管理員"],
[(name) => name[0] === "李" && name !== "李鵬", () => "小李"],];function getUserDescribe(name) {
let str; // 儲存判斷結果
const getDescribe = describeForNameMap.find((item) => item[0](name));
if (getDescribe) {
str = getDescribe[1]();
} else {
str = "此人比較神祕!";
}
// 對判斷結果str的一些處理
// ......
console.log(str);
return str;}
登入後複製
檢視優化後的getUserDescribe
函數我們能夠知道,它從describeForNameMap
獲取了一個值賦值給了str
(describeForNameMap
是如何返回值的我們並不關心),之後對str
作了一些處理。這就突出了getUserDescribe
函數的重點(對判斷結果str進行處理)。
在這個例子中
describeForNameMap
子陣列的第二個元素完全可以直接使用一個值:[(name) => name.length > 3, "名字太長"]
,但為了整體程式碼的可延伸性,推薦還是使用函數,因為函數可以接收引數,方便應對之後更復雜的場景。
分支優化在各種語言中都有不同的實現方式和應用場景,本篇通過JavaScript
介紹了兩種程式碼分支優化的思想,程式碼的實現非常簡單,重點在於這種思想的應用。
其實關於分支優化這個問題一直存在爭議,目前存在兩種觀點:
物件/陣列
,對物件/陣列
進行檢索反而比單純的if else
還是廢效能。可讀性/可維護性
更好,並且引入物件/陣列
所帶來的效能問題在當今時代根本不值一提。【相關推薦:、】
以上就是一文教你JavaScript如何實現分支優化的詳細內容,更多請關注TW511.COM其它相關文章!