>  기사  >  웹 프론트엔드  >  JavaScript로 복잡한 판단을 작성하는 우아한 방법

JavaScript로 복잡한 판단을 작성하는 우아한 방법

hzc
hzc앞으로
2020-06-16 09:51:151998검색

Premise


JS 코드를 작성할 때 종종 복잡한 논리적 판단을 접하게 됩니다. 일반적으로 if/else를 사용하거나 여러 조건부 판단을 구현하기 위해 전환할 수 있지만 이는 코드가 증가함에 따라 문제가 발생합니다. 코드의 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의 논리가 동일하면 실행이 가능하다는 것을 발견했습니다. 문과 중단을 생략하면 사례 3의 논리가 사례 2에서 자동으로 실행됩니다.

이때 어떤 학생들은 더 간단하게 작성하는 방법이 있다고 말할 것입니다.

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. 크기 속성을 통해 맵의 키-값 쌍 수를 쉽게 얻을 수 있지만 객체의 키-값 쌍 수는 수동으로만 확인할 수 있습니다.

문제를 업그레이드해야 합니다. 예전에는 버튼을 눌렀을 때 상태만 판단하면 되었습니다. 이제는 사용자의 신원도 판단해야 합니다.

/**
 * 按钮点击事件
 * @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 */}],
  //...
])

처리 논리를 캐시하는 것이 더 좋습니다. function

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번 다시 작성하는 것은 여전히 ​​조금 불편합니다. 예를 들어 ID에는 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))
}

즉, 배열 루프의 특성을 이용하여 정규 조건의 논리가 실행되므로 정규 규칙이 존재하기 때문에 공개 논리와 개별 논리를 동시에 실행할 수 있습니다. , 상상력을 발휘하고 더 많은 플레이 방법을 잠금 해제할 수 있습니다. 이 기사에서는 자세히 설명하지 않습니다.

Summary

이 기사에서는 다음을 포함하여 논리적 판단을 작성하는 8가지 방법을 배웠습니다.

  1. if/else

  2. switch

  3. 단방향 판단을 내릴 때: Object에 저장

  4. 단방향 판단 시: Map에 저장

  5. 다중 판단 시: 조건을 문자열로 연결하여 Object에 저장

  6. 다중 판단 시: 조건을 문자열로 연결하여 저장 in the Map

  7. 다중 판단을 할 때 : 조건을 문자열로 이어붙여 Object로 저장하고 Map에 저장

  8. 다중 판단을 할 때 : 조건을 일반 규칙으로 작성하고 Map에 저장 Map

이 시점에서 이 글도 끝이 납니다. 앞으로의 삶에서는 if/else/switch만 하지 마시길 바랍니다.

추천 튜토리얼: "JS Tutorial"

위 내용은 JavaScript로 복잡한 판단을 작성하는 우아한 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
이전 기사:화살표 기능 이해다음 기사:화살표 기능 이해