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 객체의 차이점은 무엇입니까?
객체에는 일반적으로 자체 프로토타입이 있으므로 객체에는 항상 "프로토타입" 키가 있습니다.
객체의 키는 문자열이나 기호만 될 수 있지만 맵의 키는 어떤 값이라도 될 수 있습니다.
크기 속성을 통해 맵의 키-값 쌍 수를 쉽게 얻을 수 있지만 객체의 키-값 쌍 수는 수동으로만 확인할 수 있습니다.
문제를 업그레이드해야 합니다. 예전에는 버튼을 눌렀을 때 상태만 판단하면 되었습니다. 이제는 사용자의 신원도 판단해야 합니다.
/** * 按钮点击事件 * @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가지 방법을 배웠습니다.
if/else
switch
단방향 판단을 내릴 때: Object에 저장
단방향 판단 시: Map에 저장
다중 판단 시: 조건을 문자열로 연결하여 Object에 저장
다중 판단 시: 조건을 문자열로 연결하여 저장 in the Map
다중 판단을 할 때 : 조건을 문자열로 이어붙여 Object로 저장하고 Map에 저장
다중 판단을 할 때 : 조건을 일반 규칙으로 작성하고 Map에 저장 Map
이 시점에서 이 글도 끝이 납니다. 앞으로의 삶에서는 if/else/switch만 하지 마시길 바랍니다.
추천 튜토리얼: "JS Tutorial"
위 내용은 JavaScript로 복잡한 판단을 작성하는 우아한 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!