Более элегантный способ написания сложных суждений в JavaScript

внешний интерфейс WeChat 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')
  }
}

Код можно увидеть, нажав кнопку логики: сделать две вещи, в зависимости от активного состояния, отправить логи в закопанную точку и перейти на соответствующую страницу, вы можете легко переписать предложенную схему этого кода, переключать представления:

/**
 * 按钮点击事件
 * @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 одинакова, оператор выполнения и break можно опустить, а случай случая 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])
}

Круче написать объект Map в es6 таким образом? В чем разница между объектом Map и объектом Object?

  1. Объект обычно имеет свой собственный прототип, поэтому объект всегда имеет ключ «прототип».
  2. Ключ объекта может быть только строкой или символами, но ключ карты может быть любым значением.
  3. Вы можете легко получить количество пар ключ-значение карты через свойство размера, в то время как количество пар ключ-значение объекта можно подтвердить только вручную.

Нам нужно эскалировать проблему. Раньше нам нужно было судить только о статусе, когда кнопка была нажата, а теперь нам также нужно судить о личности пользователя:

/**
 * 按钮点击事件
 * @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 для написания таких больших логических суждений.

Из приведенного выше примера мы видим, что когда ваша логика будет обновлена ​​до двоичной оценки, количество ваших оценок будет удвоено, а объем вашего кода будет удвоен.Как вы можете писать более освежающе в это время?

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)
}

Основная логика приведенного выше кода: объединение двух условий в строку, а также поиск и выполнение объекта 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 в качестве ключа:

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))
}

Это немного более продвинуто?

Здесь также можно увидеть разницу между Картой и Объектом.Карта может использовать любой тип данных в качестве ключа.

Теперь давайте немного повысим сложность. Что, если логика обработки статусов 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))
}

Этот способ написания уже может удовлетворить повседневные потребности, но если серьезно, то все еще немного неудобно переписывать вышеописанную функцию A 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))
}

Преимущества карты здесь более заметны, и в качестве ключей можно использовать обычные типы, поэтому возможности безграничны.Если спрос становится, для всех гостевых ситуаций должна быть отправлена ​​скрытая точка журнала, а различные ситуации состояния также требуют отдельной логической обработки. , то мы Это можно записать так:

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 способам написания логических суждений, в том числе:

  1. if/else
  2. switch
  3. При унарном решении: сохранить в объекте
  4. При унарном решении: сохранить на карте
  5. Для множественных суждений: соединение условия в строку и сохранение его в объекте
  6. Для множественных суждений: объединение условия в строку и сохранение его на карте.
  7. Для нескольких суждений: сохраните условие как объект и сохраните его на карте.
  8. При множественных суждениях: записывайте условие как обычное и сохраняйте его в Карте

На этом статья тоже подходит к концу.Пусть в вашей будущей жизни будет не только if/else/switch.

Если вас заинтересовала эта статья, подпишитесь на публичный аккаунт автора в WeChat: «Да Чжуань Чжуань Фэ».