I recently saw this piece of code while surfing the Internet:
function getUserDescribe(name) { if (name === "Xiao Liu") { console.log("Brother Liu"); } else if (name === "小红") { console.log("Sister Xiaohong"); } else if (name === "陈龙") { console.log("Master"); } else if (name === "李龙") { console.log("Master"); } else if (name === "Dapeng") { console.log("evil"); } else { console.log("This person is rather mysterious!"); } }
At first glance, I don’t feel anything unusual, but if there are 1,000 judgment conditions, is it difficult to write 1,000 if
branches according to this writing method?
If you write a large number of if
branches, and you may also have branch within branch, you can imagine that the readability and maintainability of the entire code will be greatly reduced, which will be greatly reduced in actual development. , it is indeed a rather troublesome problem, so is there any way to achieve the requirements and avoid these problems?
This involves branch optimization. Let us change our thinking and optimize the above code structure:
function getUserDescribe(name) { const describeForNameMap = { Xiao Liu: () => console.log("Brother Liu"), Xiaohong: () => console.log("Sister Xiaohong"), Chen Long: () => console.log("Master"), Li Long: () => console.log("Master"), Dapeng: () => console.log("Evil Man"), }; describeForNameMap[name] ? describeForNameMap[name]() : console.log("This person is rather mysterious!"); }
The judgments in the problem code are all simple equality judgments, then we can write these judgment conditions as an attribute into the object describeForNameMap
. The corresponding values of these attributes are The processing function after the condition is established.
After that, we only need to obtain the corresponding value in the describeForNameMap
object through the parameters received by the getUserDescribe
function. If the value exists, run the value (because the value is a function) .
In this way, the original if
branch judgment is converted into a simple key value
corresponding value, and the conditions and processing functions correspond one to one, making it clear at a glance.
So what should we do if the judgment condition in our if
branch is not just a simple equality judgment, but also has some expressions that need to be calculated? (As follows)
function getUserDescribe(name) { if (name.length > 3) { console.log("Name is too long"); } else if (name.length < 2) { console.log("Name is too short"); } else if (name[0] === "陈") { console.log("Xiao Chen"); } else if (name[0] === "李" & amp; & amp; name !== "Li Peng") { console.log("Xiao Li"); } else if (name === "Li Peng") { console.log("Administrator"); } else { console.log("This person is rather mysterious!"); } }
For code with this structure, objects cannot be introduced for branch optimization. We can introduce two-dimensional array for branch optimization:
function getUserDescribe(name) { const describeForNameMap = [ [ (name) => name.length > 3, () => console.log("Name is too long") ], [ (name) => name.length < 2, () => console.log("Name is too short") ], [ (name) => name[0] === "Chen", () => console.log("Xiao Chen") ], [ (name) => name === "Dapeng", () => console.log("Administrator") ], [ (name) => name[0] === "李" & amp; & amp; name !== "Li Peng", () => console.log("Xiao Li"), ], ]; const getDescribe = describeForNameMap.find((item) => item[0](name)); getDescribe? getDescribe[1](): console.log("This person is rather mysterious!"); }
Above we defined a describeForNameMap
array. Each element in the array represents a set of judgment conditions and execution functions (also an array). Then we use the find
method of the array. Just find the subarray in the describeForNameMap
array that meets the judgment conditions.
The describeForNameMap
object we defined in the above example is an independent structure, and we can completely extract it:
const describeForNameMap = { Xiao Liu: () => console.log("Brother Liu"), Xiaohong: () => console.log("Sister Xiaohong"), Chen Long: () => console.log("Master"), Li Long: () => console.log("Master"), Dapeng: () => console.log("Evil Man"), }; function getUserDescribe(name) { describeForNameMap[name] ? describeForNameMap[name]() : console.log("This person is rather mysterious!"); }
const describeForNameMap = [ [ (name) => name.length > 3, () => console.log("Name is too long") ], [ (name) => name.length < 2, () => console.log("Name is too short") ], [ (name) => name[0] === "Chen", () => console.log("Xiao Chen") ], [ (name) => name === "Dapeng", () => console.log("Administrator") ], [ (name) => name[0] === "李" & amp; & amp; name !== "Li Peng", () => console.log("Xiao Li"), ], ]; function getUserDescribe(name) { const getDescribe = describeForNameMap.find((item) => item[0](name)); getDescribe? getDescribe[1](): console.log("This person is rather mysterious!"); }
Through modular development, you can also write this
map
object into a separatejs
file, and then import it wherever you need to use it.
In this way, the entire getUserDescribe
function becomes very concise. Some students may ask what is the use of this? Isn’t this more troublesome? If I really don’t think if else
looks good, then I’ll just use if return
instead of else
:
function getUserDescribe(name) { if (name === "Xiao Liu") { console.log("Brother Liu"); return; } if (name === "小红") { console.log("Sister Xiaohong"); return; } if (name === "Chen Long") { console.log("Master"); return; } if (name === "李龙") { console.log("Master"); return; } if (name === "Dapeng") { console.log("evil"); return; } console.log("This person is rather mysterious!"); }
Just imagine, if you have 1000 judgment branches in your getUserDescribe
function, and also have a large number of processing codes that are executed based on the judgment results, and the getUserDescribe
function will return this processed code The value of the judgment result.
At this time, the emphasis of the getUserDescribe
function lies in the processing of the judgment result, not in which branch the result is obtained, for example:
function getUserDescribe(name) { let str; if (name.length > 3) { str = "Name is too long"; } else if (name.length < 2) { str = "Name is too short"; } else if (name[0] === "陈") { str = "Xiao Chen"; } else if (name[0] === "李" & amp; & amp; name !== "Li Peng") { str = "Xiao Li"; } else if (name === "Li Peng") { str = "Administrator"; } else { str = "This person is rather mysterious!"; } console.log(str); return str; }
If you do not perform branch optimization, the getUserDescribe
function will be occupied by a large number of if
branches, making the focus of the getUserDescribe
function lost ( The getUserDescribe
function focuses on the processing of the judgment result, not on which branch the result is obtained through). Now you can take a look at our optimized code:
const describeForNameMap = [ [(name) => name.length > 3, () => "Name is too long"], [(name) => name.length < 2, () => "Name is too short"], [(name) => name[0] === "Chen", () => "Xiao Chen"], [(name) => name === "Dapeng", () => "Administrator"], [(name) => name[0] === "李" & amp; & amp; name !== "Li Peng", () => "小李"], ]; function getUserDescribe(name) { let str; const getDescribe = describeForNameMap.find((item) => item[0](name)); if (getDescribe) { str = getDescribe[1](); } else { str = "This person is rather mysterious!"; } console.log(str); return str; }
Looking at the optimized getUserDescribe
function, we can know that it obtains a value from describeForNameMap
and assigns it to str
(describeForNameMap
We don’t care how to return the value), and then did some processing on str
. This highlights the focus of the getUserDescribe
function (processing the judgment result str).
In this example, the second element of the
describeForNameMap
subarray can directly use a value:[(name) => name.length > 3, "Name is too long"]
, but for the scalability of the overall code, it is recommended to use functions, because functions can receive parameters, making it easier to deal with more complex scenarios in the future.
Branch optimization has different implementation methods and application scenarios in various languages. This article introduces two ideas of code branch optimization through JavaScript
. The implementation of the code is very simple. , the focus is on the application of this idea.
In fact, there has always been controversy about the issue of branch optimization. There are currently two views:
-
View 1: There is no need to bother optimizing it at all, and the optimized code creates an extra
object/array
, which is better forobject/array
Retrieval is a waste of performance compared to simplyif else
. -
View 2: The code after branch optimization has better
readability/maintainability
and introduces the performance issues caused byobject/array
Not worth mentioning in this day and age.
What’s your opinion?