JavaScript | 1000 judgment conditions require writing 1000 if? This article teaches you how to implement branch optimization

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 separate js 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 (describeForNameMapWe 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 for object/array Retrieval is a waste of performance compared to simply if else.

  • View 2: The code after branch optimization has better readability/maintainability and introduces the performance issues caused by object/array Not worth mentioning in this day and age.

What’s your opinion?