ホームページ >ウェブフロントエンド >jsチュートリアル >ある記事では、分岐最適化の場合に JavaScript を実装する方法を説明しています。

ある記事では、分岐最適化の場合に JavaScript を実装する方法を説明しています。

青灯夜游
青灯夜游転載
2023-03-14 19:37:131986ブラウズ

1000の判定条件には1000のifを書く必要がある? if 分岐ステートメントを最適化するにはどうすればよいですか?次の記事ではブランチの最適化を実現する方法について説明しますので、皆様のお役に立てれば幸いです。

ある記事では、分岐最適化の場合に JavaScript を実装する方法を説明しています。

最近、インターネットサーフィン中に次のコードを見つけました:

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個、この書き方だとif分岐を1000個書くのは難しいでしょうか?

多数の if ブランチを記述し、ブランチ 内に ブランチも存在する可能性がある場合、コード全体の可読性と保守性が低下すると想像できます。実際の開発ではこれが頭の痛い問題ですが、これらの問題を回避しながら要件を達成する方法はあるのでしょうか? [推奨学習: JavaScript ビデオ チュートリアル ]

1️⃣ 簡単なブランチの最適化

これには ブランチの最適化 が含まれます。変更しましょう私たちの考え方と上記のコード構造を最適化します。

function getUserDescribe(name) {
    const describeForNameMap = {
        小刘: () => console.log("刘哥哥"),
        小红: () => console.log("小红妹妹"),
        陈龙: () => console.log("大师"),
        李龙: () => console.log("师傅"),
        大鹏: () => console.log("恶人"),
    };
    describeForNameMap[name] ? describeForNameMap[name]() : console.log("此人比较神秘!");
}

問題コード内の判定はすべて単純な 均等判定 であるため、これらの判定条件をオブジェクト の属性として記述することができます。 descriptionForNameMap、これらの属性に対応する値が条件成立後の処理関数となります。

その後は、getUserDescribe 関数で受け取ったパラメーターを通じて、describeForNameMap オブジェクト内の対応する値を取得するだけです。値が存在する場合は、その値を実行します。 (値は関数であるため)。

このように、元の if 分岐判定は、単純な key value 対応値に変換され、条件と処理関数が 1 対 1 に対応して明確になります。一目でわかる。

2️⃣ 複雑な分岐の最適化

次に、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("此人比较神秘!");
    }
}

この構造のコードでは、分岐最適化のためにオブジェクトを導入できません。分岐最適化のために 2 次元配列 を導入できます:

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 配列内で判定条件を満たす部分配列を見つけます。

3️⃣ ブランチの切り離し

上の例で定義した 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 ファイルに記述し、それを使用する必要がある場所にインポートすることもできます。それでおしまい。

4️⃣ 論争

このようにして、getUserDescribe 関数全体が非常に簡潔になります。これに何の意味があるのか​​と尋ねる学生もいるかもしれません。 ?何を使うか?こっちの方が面倒じゃないですか? if else が本当に適切ではない場合は、else の代わりに if return を使用します。

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 関数の focus は、どの分岐で結果が得られるかではなく、 判定結果の処理にあります。例:

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 Lost の関数に焦点を当てます (getUserDescribeFunction焦点は判定結果の処理です。 結果がどのブランチを通じて得られるかではありません)。最適化されたコード:

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

サブ配列の 2 番目の要素で値を直接使用できます:[(name) => name.length > 3 , "Nameは長すぎます"] ただし、コード全体のスケーラビリティを考慮すると、関数を使用することをお勧めします。関数はパラメーターを受け取ることができるため、将来的により複雑なシナリオに対処しやすくなります。

? 結論

ブランチの最適化さまざまな言語でさまざまな実装方法とアプリケーション シナリオが存在します。この記事では JavaScript を使用します。コード ブランチの最適化に関する 2 つのアイデアを紹介します。コードの実装は非常にシンプルで、このアイデアの適用に重点が置かれています。

実は、ブランチの最適化の問題については議論があり、現在 2 つのビューがあります:

  • ビュー 1: わざわざ行う必要はありません最適化と最適化 次のコードは追加の オブジェクト/配列 を作成するため、 オブジェクト/配列 を取得することは、単純に if else を実行するよりもさらに無駄です。
  • 視点 2: ブランチ最適化後のコード 可読性/保守性 は向上しており、object/array の導入によりパフォーマンスの問題が発生します。この時代では言及する価値はありません。 #########あなたの意見は何ですか?
プログラミング関連の知識について詳しくは、

プログラミング教育

をご覧ください。 !

以上がある記事では、分岐最適化の場合に JavaScript を実装する方法を説明しています。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。