ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScriptで複雑な論理判断を行うための技術的な書き方(コード例)

JavaScriptで複雑な論理判断を行うための技術的な書き方(コード例)

不言
不言転載
2018-11-23 15:29:383103ブラウズ

この記事では、JavaScript での複雑な論理的判断に関する技術的な記述方法 (コード例) を紹介します。必要な方は参考にしていただければ幸いです。

JS コードを作成するときに、複雑な論理判断が発生することがよくあります。通常、if/else または switch を使用して複数の条件判断を実装できますが、ロジックが複雑になると問題が発生します。速度が上がると、コード内の if/else/switch がますます肥大化し、理解しにくくなります。そこで、この記事で判定ロジックをよりエレガントに記述する方法を試してみましょう。

最初にコードを見てください

/**

 * 按钮点击事件

 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消

 */
const onButtonClick = (status) => {

  if (status == 1) {

    sendLog('processing') jumpTo('IndexPage')

  } else if (status == 2) {

    sendLog('fail') jumpTo('FailPage')

  } else if (status == 3) {

    sendLog('fail') jumpTo('FailPage')

  } else if (status == 4) {

    sendLog('success') jumpTo('SuccessPage')

  } else if (status == 5) {

    sendLog('cancel') jumpTo('CancelPage')

  } else {

    sendLog('other') jumpTo('Index')

  }

}

コードを通してこのボタンのクリック ロジックを確認できます。次の 2 つのことを行います。さまざまなアクティビティの状態に応じて、ログを送信してポイントを埋め、対応するページにジャンプします。このコードの書き換え計画を簡単に提案できます。

/**
 * 按钮点击事件
 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消
 */
const onButtonClick = (status) => {
  switch (status) {

    case 1:

      sendLog('processing')

      jumpTo('IndexPage')

      break

    case 2:

    case 3:

      sendLog('fail')

      jumpTo('FailPage')

      break

    case 4:

      sendLog('success')

      jumpTo('SuccessPage')

      break

    case 5:

      sendLog('cancel')

      jumpTo('CancelPage')

      break

    default:

      sendLog('other')

      jumpTo('Index')

      break

  }

}

そうですね、これはより明確に見えます。 if/else には注意してください。ケース 2 とケース 3 のロジックが同じ場合、実行ステートメントを省略して、ケース 2 でケース 3 のロジックが自動的に実行されます。

この時点で、学生の中には、もっと簡単に書く方法があると言う人もいます。

const actions = {

  '1': ['processing', 'IndexPage'],

  '2': ['fail', 'FailPage'],

  '3': ['fail', 'FailPage'],

  '4': ['success', 'SuccessPage'],

  '5': ['cancel', 'CancelPage'],

  'default': ['other', 'Index'],

}

/**

 * 按钮点击事件

 * @param {number} status 活动状态:1开团进行中 2开团失败 3 商品售罄 4 开团成功 5 系统取消

 */

const onButtonClick = (status) => {

  let action = actions[status] || actions['default'],

    logName = action[0],

    pageName = action[1]

  sendLog(logName)

  jumpTo(pageName)

}

この方法の賢い点は、判定条件を使用していることです。属性名はオブジェクトの属性値として処理ロジックを使用し、ボタンがクリックされたときにオブジェクトの属性を検索して論理的に判定するため、特に単項の条件判定に適した記述方法です。

他の書き方はありますか?一部:

const actions = new Map([

  [1, ['processing', 'IndexPage']],

  [2, ['fail', 'FailPage']],

  [3, ['fail', 'FailPage']],

  [4, ['success', 'SuccessPage']],

  [5, ['cancel', 'CancelPage']],

  ['default', ['other', 'Index']]

])

/**

 * 按钮点击事件

 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消

 */

const onButtonClick = (status) => {

  let action = actions.get(status) || actions.get('default')

  sendLog(action[0])

  jumpTo(action[1])

}

es6 では Map オブジェクトを使用してこのように書くともっと楽しくなりませんか? Map オブジェクトと Object オブジェクトの違いは何ですか?

1. 通常、オブジェクトには独自のプロトタイプがあるため、オブジェクトには常に「プロトタイプ」キーがあります。

2. オブジェクトのキーは文字列またはシンボルのみですが、マップのキーは任意の値にすることができます。

3. マップのキーと値のペアの数は size 属性を通じて簡単に取得できますが、オブジェクトのキーと値のペアの数は手動でのみ確認できます。

以前は、ボタンをクリックしたときのステータスを判断するだけでよかった問題をアップグレードする必要があります。

/**

 * 按钮点击事件

 * @param {number} status 活动状态:1开团进行中 2开团失败 3 开团成功 4 商品售罄 5 有库存未开团

 * @param {string} identity 身份标识:guest客态 master主态

 */

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

    }

  }

}

ごめんなさい。コードが冗長すぎるため、各判断の具体的なロジックを記述します。

また if/else を使用することをご容赦ください。論理的判断のこのような大規模なセクションを記述するために、今でも if/else を使用している人がたくさんいるためです。

上記の例から、ロジックを二項判定にアップグレードすると、判定量が2倍になり、コード量も2倍になることがわかります。このとき、よりすっきりと書くにはどうすればよいでしょうか。

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*/ }],

])



/**

 * 按钮点击事件

 * @param {string} identity 身份标识:guest客态 master主态

 * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 开团成功 4 商品售罄 5 有库存未开团

 */

const onButtonClick = (identity, status) => {

  let action = actions.get(`${identity}_${status}`) || actions.get('default')

  action.call(this)

}

上記のコードの中心となるロジックは、2 つの条件を文字列に結合し、条件文字列をキーとして、処理関数を値として使用して Map オブジェクトを検索して実行するというものです。この記述方法は次のとおりです。複数で使用されます。特に条件判断をする場合に便利です。

もちろん、上記のコードが 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)

}

如果有些同学觉得把查询条件拼成字符串有点别扭,那还有一种方案,就是用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))

}

もう少し高度ですか?

Map と Object の違いは、ここでも確認できます。Map は任意のタイプのデータをキーとして使用できます。

ここで、ステータス 1 ~ 4 の処理ロジックがゲストの場合と同じである場合はどうなるかを少しアップグレードします。最悪のケースは次のとおりです。

const actions = new Map([

  [{

    identity: 'guest',

    status: 1

  }, () => { /* functionA */ }],

  [{

    identity: 'guest',

    status: 2

  }, () => { /* functionA */ }],

  [{

    identity: 'guest',

    status: 3

  }, () => { /* functionA */ }],

  [{

    identity: 'guest',

    status: 4

  }, () => { /* functionA */ }],

  [{

    identity: 'guest',

    status: 5

  }, () => { /* functionB */ }],

  //...

])

より良い方法です。処理ロジック関数をキャッシュする:

const actions = () => {

  const functionA = () => { /*do sth*/ }

  const functionB = () => { /*do sth*/ }

  return new Map([

    [{

      identity: 'guest',

      status: 1

    }, functionA],

    [{

      identity: 'guest',

      status: 2

    }, functionA],

    [{

      identity: 'guest',

      status: 3

    }, functionA],

    [{

      identity: 'guest',

      status: 4

    }, functionA],

    [{

      identity: 'guest',

      status: 5

    }, functionB],

    //...

  ])

}



const onButtonClick = (identity, status) => {

  let action = [...actions()].filter(([key, value]) => (key.identity == identity && key.status == status))

  action.forEach(([key, value]) => value.call(this))

}

このように書けば日常的なニーズは満たせますが、正直なところ、判定条件が特に複雑になる場合に上記の functionA を 4 回書き直すのはまだ少し面倒です。たとえば、アイデンティティには 3 つの状態があり、ステータスには 10 の状態があります。その場合、30 個の処理ロジックを定義する必要がありますが、これらのロジックの多くは同じであることが多いです。

const actions = () => {

  const functionA = () => { /*do sth*/ }

  const functionB = () => { /*do sth*/ }

  return new Map([

    [/^guest_[1-4]$/, functionA],

    [/^guest_5$/, functionB],

    //...

  ])

}



const onButtonClick = (identity, status) => {

  let action = [...actions()].filter(([key, value]) => (key.test(`${identity}_${status}`)))

  action.forEach(([key, value]) => value.call(this))

}

ここでは、Map の利点がより際立ちます。通常の型をキーとして使用できるため、需要が変化した場合は、すべてのログ埋め込みポイントを送信する必要があります。ゲストの状況、およびさまざまなステータスの状況にも個別の論理処理が必要です。 そして、次のように書くことができます。

const actions = () => {

  const functionA = () => { /*do sth*/ }

  const functionB = () => { /*do sth*/ }

  const functionC = () => { /*send log*/ }

  return new Map([

    [/^guest_[1-4]$/, functionA],

    [/^guest_5$/, functionB],

    [/^guest_.*$/, functionC],

    //...

  ])

}



const onButtonClick = (identity, status) => {

  let action = [...actions()].filter(([key, value]) => (key.test(`${identity}_${status}`)))

  action.forEach(([key, value]) => value.call(this))

}

つまり、配列ループの特性を使用して、規則的な条件を満たすロジックが実行されます。その後、通常のルールが存在するため、公開ロジックと個別ロジックを同時に実行できるため、より多くの遊び方を開くことができます。この記事では詳しく説明しません。

概要

この記事では、次のような論理的な判断を書くための 8 つの方法を説明しました。

  • if/else

  • switch

  • 1つの要素で判断する場合:オブジェクトに保存

  • 1つの要素で判断する場合: マップに保存

  • 複数判定の場合: 条件を文字列化してオブジェクトに保存

  • 複数判定の場合:条件を文字列に結合し、In Mapに保存します。

  • 複数の判定を行う場合:条件をObjectとして保存し、Mapに保存します。

  • 複数の判定を行う場合: 条件を正規表現としてマップに保存します

この時点で、あなたの今後の人生が終わりにならないことを祈ります。 if/else/switch のみがあります。

以上がJavaScriptで複雑な論理判断を行うための技術的な書き方(コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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