ホームページ > 記事 > ウェブフロントエンド > if else を削除してコードをよりエレガントに見せる
まえがき
#こんな目に遭った学生も多いはず。このような if else でいっぱいのコードを見たことがありますが、このような混乱に直面して、単純かつ粗雑に段階的な変更を続けても、多くの場合、複雑さがますます増し、可読性がますます悪化するだけです。次に、リファクタリングを行います。数分かけてこの記事を読んでください。役立つかもしれません。シナリオ 1: ステータスに応じて対応する名前を表示
最適化計画 1: オブジェクト objectconst statusStr = { '1': '待付款', '2': '待发货', '3': '已发货', '4': '交易完成', '5': '交易关闭', 'default': '', } const getStatus = (status) =>{ return statusStr[status] || statusStr['default'] }判定します 条件をオブジェクトの属性名、処理ロジックをオブジェクトの属性値とし、ボタンをクリックするとオブジェクトの属性を検索して論理判定を行います。
最適化計画 2: Map オブジェクト
const statusStr = new map([ '1': ['待付款'], '2': ['待发货'], '3': ['已发货'], '4': ['交易完成'], '5': ['交易关闭'], 'default': [''], ]) const getStatus = (status) =>{ let actions = statusStr.get(status) || statusStr.get('default') return actions[0]; }この記事では es6 の Map オブジェクトを使用していますが、Map オブジェクトと Object オブジェクトの違いは何でしょうか? オブジェクトには通常、独自のプロトタイプがあるため、オブジェクトには常に「プロトタイプ」キーがあります。 オブジェクトのキーには文字列またはシンボルのみを指定できますが、マップのキーには任意の値を指定できます。 マップ内のキーと値のペアの数は、size 属性を通じて簡単に取得できますが、オブジェクト内のキーと値のペアの数は手動でのみ確認できます。 シナリオ 2: 名前に対応する複数の条件
さあ、問題をアップグレードしましょう。以前は、ボタンをクリックするときに必要なのは、次のことだけでした。ステータスを判断しますが、ユーザーの身元を判断する必要があります。 「例:」
const onButtonClick = (status,identity)=>{ if(identity == 'guest'){ if(status == 1){ //do sth }else if(status == 2){ //do sth }else if(status == 3){ //do sth }else if(status == 4){ //do sth }else if(status == 5){ //do sth }else { //do sth } }else if(identity == 'master') { if(status == 1){ //do sth }else if(status == 2){ //do sth }else if(status == 3){ //do sth }else if(status == 4){ //do sth }else if(status == 5){ //do sth }else { //do sth } } }
上記の例から、ロジックが二項判断にアップグレードされると、判断量が増加することがわかります。コードの量も 2 倍になりますが、このときどうすればもっとわかりやすく書けるのでしょうか?
最適化計画 1: 文字結合の形式で条件を Map オブジェクトに保存します。
const actions = new Map([ ['guest_1', ()=>{/*do sth*/}], ['guest_2', ()=>{/*do sth*/}], ['guest_3', ()=>{/*do sth*/}], ['guest_4', ()=>{/*do sth*/}], ['guest_5', ()=>{/*do sth*/}], ['master_1', ()=>{/*do sth*/}], ['master_2', ()=>{/*do sth*/}], ['master_3', ()=>{/*do sth*/}], ['master_4', ()=>{/*do sth*/}], ['master_5', ()=>{/*do sth*/}], ['default', ()=>{/*do sth*/}], ]) const onButtonClick = (identity,status)=>{ let action = actions.get(`${identity}_${status}`) || actions.get('default') action.call(this) }上記のコードの中心となるロジックは次のとおりです。 2 つの条件を結合します。文字列を渡し、条件連結文字列をキー、処理関数を値としてMapオブジェクトを検索して実行するこの書き方は、特に複数の条件を判定する場合に便利です。
最適化計画 2: 条件を文字結合の形式で Object オブジェクトに格納します。
const actions = { 'guest_1':()=>{/*do sth*/}, 'guest_2':()=>{/*do sth*/}, //.... } const onButtonClick = (identity,status)=>{ let action = actions[`${identity}_${status}`] || actions['default'] action.call(this) }最適化計画 3: 条件を Map オブジェクトに格納しますObject オブジェクトの形式で
クエリ条件を文字列に記述するのは少し面倒かもしれません。別の解決策として、Map オブジェクトを使用し、Object オブジェクトをkey:
const actions = new Map([ [{identity:'guest',status:1},()=>{/*do sth*/}], [{identity:'guest',status:2},()=>{/*do sth*/}], //... ]) const onButtonClick = (identity,status)=>{ let action = [...actions].filter(([key,value])=>(key.identity == identity && key.status == status)) action.forEach(([key,value])=>value.call(this)) }シナリオ 3: ステータスに基づいて対応する操作を行う
「例を示してください:」
function init () { if (isAnswer === 1) { if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } } else if (isAnswer === 2) { if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } } else if (isAnswer === 3) { if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } } }
最適化計画 1: ルックアップ テーブル、責任連鎖ルックアップ テーブル
const rules = [
{
match (an, old) {if (an === 1) {return true}},
action (an, old) {
if (old === 1) {// ...}
else if (old === 2) {// ...}
}
},
{
match (an, old) { if (an === 2) {return true } },
action (an, old) {
if (old === 1) {// ...}
else if (old === 2) {// ...}
}
},
{
match (an, old) {if (an === 3) {return true}},
action (an, old) {
if (old === 1) {// ...}
else if (old === 2) {// ...}
}
}
]
function init (an, old) {
for (let i = 0; i < rules.length; i++) {
// 如果返回true
if (rules[i].match(an, old)) {
rules[i].action(an, old)
}
}
}
init(isAnswer, isOldUser)
根本原因ではなく症状を治療しているように見えるかもしれませんが、実際はそうではありません。 init 関数の複雑さは大幅に軽減されます。制御プロセスの複雑なロジックを、determineAction 関数に分割しました
最適化計画 2: 関数型プログラミング
import R from 'ramda' var fn = R.cond([ [R.equals(0), R.always('water freezes at 0°C')], [R.equals(100), R.always('water boils at 100°C')], [R.T, temp => 'nothing special happens at ' + temp + '°C'] ]); fn(0); //=> 'water freezes at 0°C' fn(50); //=> 'nothing special happens at 50°C' fn(100); //=> 'water boils at 100°C'シナリオ 4: さまざまな実行スコープに応じた処理
「例:」 たとえば、次のようなニーズが発生する可能性があります: たとえば、特定のプラットフォームの信用スコア評価が 700 を超えている場合など-950、それは信用が優れています、650-700は信用が優れています、600-650は信用が良好です、550-600は信用が中程度、350-550は信用が不良です。
function showGrace(grace) { let _level=''; if(grace>=700){ _level='信用极好' } else if(grace>=650){ _level='信用优秀' } else if(grace>=600){ _level='信用良好' } else if(grace>=550){ _level='信用中等' } else{ _level='信用较差' } return _level; }
最適化計画 1: ルックアップ テーブルを使用して構成データとビジネス ロジックを分離する
function showGrace(grace,level,levelForGrace) { for(let i=0;i<level.length;i++){ if(grace>=level[i]){ return levelForGrace[i]; } } //如果不存在,那么就是分数很低,返回最后一个 return levelForGrace[levelForGrace.length-1]; } let graceForLevel=[700,650,600,550]; let levelText=['信用极好','信用优秀','信用良好','信用中等','信用较差'];概要
多くの場合、より柔軟な方法を使用して if else と switch を置き換えることができますが、状況によってはすべての if else を置き換える必要があるわけではありません。
その他の関連する無料学習:javascript(ビデオ)
以上がif else を削除してコードをよりエレガントに見せるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。