클린코드 자바스크립트 [5] 분기 다루기

Doozuu·2023년 12월 7일
0

Javascript

목록 보기
92/99

값식문

문법 에러가 발생하면 서비스 오류가 발생할 가능성이 있다.
따라서 문법을 잘 지키도록 노력해야 한다.

// JSX
<div id={if(condition) {'msg'}}>Hello World!</div>

// const obj = {id : if(condition) {'msg'}} 
// 객체의 값으로 if문이 들어가고 있다.
// 객체의 값으로는 값만 들어갈 수 있기 때문에 위와 같이 작성하면 문법 에러가 발생한다.
React.createElement("div", {id: if(condition) {'msg'}}, "Hello World!");

// 아래처럼 삼항연산자로 작성하면 에러가 발생하지 않는다.
// 삼항연산자는 식이고, 이는 값으로 귀결되기 때문이다.
ReactDOM.render(<div id={condition ? 'msg' : null}>Hello World!</div>, mountNode);

아래에서 switch문을 사용했는데도 문법 에러가 발생하지 않는 이유는?

즉시 실행 함수(IIFE) 를 사용했기 때문!
-> {} 내부에는 값이나 식만 들어갈 수 있는데, 즉시 실행 함수는 바로 값을 반환하기 때문에 사용할 수 있다.

<p>
  {(() => {
    switch (this.state.color) {
      case "red":
        return "#FF0000";
      case "green":
        return "#00FF00";
      case "blue":
        return "#0000FF";
    }
  })()}
</p>;

if문 대신 논리 연산자를 사용할 수도 있다. (||, &&)

<p>{this.state.color || 'white'}</p>

배열에 있는 값을 화면에 하나씩 출력하고 싶을 때, for문을 사용하면 즉시 실행 함수로 만들어야 하고 값을 임시 변수에 저장해두었다 return해야 하기 때문에 굉장히 복잡해진다.

{
  (() => {
    const rows = [];
    for (let i = 0; i < objectRows.length; i++) {
      rows.push(<p key={i} data={objectRows[i]}></p>);
    }
    return rows;
  })();
}

이럴때는 고차 함수(map, filter 등)를 사용하면 간단하게 표현할 수 있다.

{
  objectRows.map((obj, i) => <p key={i} data={obj}></p>);
}

JSX는 Babel로 트랜스파일링되면 객체로 바뀌는데, 객체 내부에는 값과 식만 넣을 수 있으므로 if문, for문, switch문 등을 넣을 수 없다. 따라서 논리 연산자, 삼항 연산자, 고차 함수, 즉시 실행 함수를 활용하는 것이 좋다.



삼항연산자 다루기

삼항연산자를 이용해 과도하게 숏코딩 하기 보다는 일관성을 유지하는 것이 좋다.

1. 조건이 많을 때는 switch문 사용하기

조건문이 여러개일 때, 삼항연산자나 if문을 사용하기 보다는 switch문을 사용하는 것이 좋다.
-> 가독성 측면에서 더 좋다.


2. () 를 이용해 우선순위 나타내주기

const example = condition ? a === 0 ? 'zero' : 'positive' : 'negative'

// 아래처럼 괄호로 묶어 가독성을 높혀준다.
const example = condition ? (a === 0 ? 'zero' : 'positive') : 'negative'

3. 삼항연산자는 값을 반환할 때 쓰기

alert()는 void를 반환하는 함수이다.
void는 '없음'을 나타내기 때문에 undefined가 들어가게 된다.

function alertMessage(isAdult) {
  isAdult ? alert("입장 가능") : alert("입장 불가능");
}

위와 같이 나타내기 보다는 if문을 사용하는 것이 더 좋다.

function alertMessage(isAdult) {
  if (isAdult) {
    alert("입장 가능");
  } else {
    alert("불입장 가능");
  }
}

삼항연산자는 값을 반환할 때 사용하는 것이 좋다.

function alertMessage(isAdult) {
  const m = isAdult ? "입장 가능" : "입장 불가능";
}

조건에 따라 참, 거짓이 모두 필요한게 아니라 참이나 거짓만 필요한 경우에는 truthy/falsy 를 사용하는 게 좋다.



Truthy, Falsy

  • Truthy : 참 같은 값, 참으로 평가되는 값
  • Falsy : 거짓 같은 값, 거짓으로 평가되는 값

Truthy

if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)

Falsy

if (false) {
  // 도달할 수 없습니다.
}

if (null) {
  // 도달할 수 없습니다.
}

if (undefined) {
  // 도달할 수 없습니다.
}

if (0) {
  // 도달할 수 없습니다.
}

if (-0) {
  // 도달할 수 없습니다.
}

if (0n) {
  // 도달할 수 없습니다.
}

if (NaN) {
  // 도달할 수 없습니다.
}

if ("") {
  // 도달할 수 없습니다.
}

예시

이름이 비어있는지 확인해야 할 때

function printName(name) {
  if (name === undefined || name === null) {
    return "없음";
  }
  return "안녕" + name;
}

문자열은 truthy이기 때문에, !를 붙여 falsy로 만들어서 사용할 수 있다.

function printName(name) {
  if (!name) {
    return "없음";
  }
  return "안녕" + name;
}



단축 평가

AND : 모두가 참이어야 참
OR : 하나라도 참이면 참

true && false && '도달 x' // false를 만나면 멈춤
true || true || '도달 x' // 첫 true를 만나면 멈춤

단축 평가를 이용해 if문을 줄일 수 있다.

예시 1

function fetchData() {
  // if문 사용했을 때
  if (state.data) {
    return state.data;
  } else {
    return "Fetching...";
  }

  // 단축평가 사용했을 때
  return state.data || "Fetching...";
}

예시 2

function dog(name) {
  let dogName;
  
  if (name) {
    dogName = name;
  } else {
    dogName = "냐옹";
  }

  return dogName + "입니다";
}

아래처럼 임시 변수를 만들지 않고 바로 나타낼 수 있다.

function dog(name) {
  return (name || "냐옹") + "입니다";
}

예시 3

중첩되는 if문이 있을 때

function getUserName(user, isLogin) {
  if (isLogin) {
    if (user) {
      if (user.name) {
        return user.name;
      } else {
        return "이름없음";
      }
    }
  }
}

아래처럼 간결하게 나타낼 수 있다.

function getUserName(user, isLogin) {
  if (isLogin && user) {
    return user.name || "이름없음";
  }
}

혹은 아래처럼도 가능하다.

function getUserName(user, isLogin) {
  return isLogin && user && (user.name || "이름없음");
}



else if 피하기

x가 0보다 큰 경우 첫 번째 메세지만 출력된다.
나열되어 있어서 두 번째 메세지도 출력될 것 같다는 착각을 줄 수 있다.

if (x >= 0) {
  console.log("x는 0과 같거나 크다");
} else if (x > 0) {
  console.log("x는 0보다 크다");
}

위의 식은 아래와 동일하다.

if (x >= 0) {
  console.log("x는 0과 같거나 크다");
} else {
  if (x > 0) {
    console.log("x는 0보다 크다");
  }
}

방법

  1. else if 대신 if문으로 다 작성해준다.
if (x >= 0) {
  console.log("x는 0과 같거나 크다");
}
if (x > 0) {
  console.log("x는 0보다 크다");
}
  1. 조건이 많으면 switch문으로 작성한다.



else 피하기

function getUserName(user) {
  if (user.name) {
    return user.name;
  } else {
    return "이름없음";
  }
}

if문에서 return이 실행되면 어차피 아래 return문은 실행되지 않는다.
따라서 굳이 else를 사용하지 않고 아래처럼 나타내는게 좋다.

function getUserName(user) {
  if (user.name) {
    return user.name;
  }

  return "이름없음";
}

Early Return

아래와 같이 복잡한 로직의 로그인 처리 코드가 있을 때

function login(isLogin, user) {
  if (!isLogin) {
    if (checkToken()) {
      if (!user.name) {
        return registerUser(user);
      } else {
        refreshToken();
        return "로그인 성공";
      }
    } else {
      throw new Error("No Token");
    }
  }
}

조건들을 분리하여 early return을 하면 가독성이 좋아진다.

function login(isLogin, user) {
  if (isLogin) {
    return;
  }

  if (!checkToken()) {
    throw new Error("No Token");
  }

  if (!user.name) {
    return registerUser(user);
  }

  refreshToken();

  return "로그인 성공";
}



부정 조건문 지양하기

지양해야 하는 이유

  1. 생각을 여러번 해야 할 수 있다.(헷갈려서 실수할 수 있음)
    ex. isNaN
  2. 프로그래밍 언어 자체로 if문이 처음부터 오고 true부터 실행시킨다.
if(!Number.isNaN(3)){} // x

if(isNumber(3){} // o

부정 조건 예외

  1. early return
  2. 유효성 검증
  3. 보안 혹은 검사하는 로직



Default Case 고려하기

  • 함수에 아무 값도 넘기지 않을 때를 대비해 기본 값을 설정해두는 것이 좋다.
  • 사용자가 실수할 때를 대비하여 예외처리를 해두는 것이 필요하다.
  • React에서도 <Switch>를 사용하여 특정 주소에 해당하는 페이지가 없을 때 Not Found 페이지를 보여주도록 하는 것이 좋다.



명시적인 연산자 사용 지양하기

괄호를 이용해 우선순위를 명시적으로 나타내주는게 좋다.
예측 가능하고 디버깅 하기 쉽도록 작성한다.

몸무게 + 신장 신장 -> 몸무게 + (신장 신장)
로그인 && 토큰 || 유저 -> (로그인 && 토큰) || 유저
number-- -> number = number - 1



Nullish coalescing operator

널 병합 연산자 ??

  • null이거나 undefined인지 체크하고 싶을 때 : ??

  • falsy 체크하고 싶을 때 : ||

  • 연산자 우선순위가 낮다.

  • || 랑 ?? 는 함께 쓸 수 없다.(함께 쓰려면 괄호로 구분해야 함)



드모르간의 법칙

위 보다는 아래처럼 나타내는게 좋다.

if(!(A || B)){
}

if(!A && !B){
}
profile
모든게 새롭고 재밌는 프론트엔드 새싹

0개의 댓글