JS 조건문을 작성하기 위한 팁

정현승·2024년 10월 22일

1. 조건문이 반복된다면 includes 메소드를 활용

간단한 조건문이지만 만약 과일 종류가 더 늘어난다면 난잡한 코드가 될것입니다.

function test(fruit) {
  if (fruit == 'apple' || fruit == 'strawberry') {
    console.log('red');
  }
}
function test(fruit) {
  if (
    fruit == "apple" ||
    fruit == "strawberry" ||
    fruit === "cherry" ||
    fruit === "cranberries"
  ) {
    console.log("red");
  }
}

Array.includes()를 사용하면 훨씬 가독성이 좋아집니다.

function test(fruit) {
  // extract conditions to array
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  if (redFruits.includes(fruit)) {
    console.log('red');
  }
}

과일이 더 추가되어도 배열에 과일을 추가해주면 됩니다.

2. 조건문의 중첩은 지양하고 리턴은 빠르게

두 가지 조건을 더 포함하여 이전 예제를 확장

  • 과일이 제공되지 않으면 오류 발생하시오
  • 10을 초과하는 경우 과일 수량을 수용하고 출력하시오
function test(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  // condition 1: fruit must has value
  if (fruit) {
    // condition 2: must be red
    if (redFruits.includes(fruit)) {
      console.log('red');
 
      // condition 3: must be big quantity
      if (quantity > 10) {
        console.log('big quantity');
      }
    }
  } else {
    throw new Error('No fruit!');
  }
}
 
// test results
test(null); // error: No fruits
test('apple'); // print: red
test('apple', 20); // print: red, big quantity

(매우 어지럽고 가독성이 떨어지는 모습)

  • 과일이 제공되지 않으면 오류 발생하시오
    과일이 없다면 그 즉시 바로 오류를 발생시키는 게 훨씬 좋습니다. early return을 하겠습니다.
function test(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  // condition 1: throw error early
  if (!fruit) throw new Error('No fruit!');
 
  // condition 2: must be red
  if (redFruits.includes(fruit)) {
    console.log('red');
 
    // condition 3: must be big quantity
    if (quantity > 10) {
      console.log('big quantity');
    }
  }
}

early return 을 사용하여 중첩을 한 단계 벗겨냈습니다.
throw와 Error의 역할

  • throw : JavaScript 실행 흐름을 중단하고 예외를 던집니다.
  • new Error() : 에러 객체를 생성하며, 이 객체는 오류에 대한 메시지와 스택 추적 정보를 포함할 수 있습니다.

여기서 한 번 더 줄일 수 있습니다.

function test(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  if (!fruit) throw new Error('No fruit!'); // condition 1: throw error early
  if (!redFruits.includes(fruit)) return; // condition 2: stop when fruit is not red
 
  console.log('red');
 
  // condition 3: must be big quantity
  if (quantity > 10) {
    console.log('big quantity');
  }
}

이제 코드에서 중첩문이 사라졌습니다.

적은 중첩 및 조기 반환을 목표로 하되 과도하게 사용하면 좋지 않다는 이야기도 있습니다.

3. 기본 함수 매개변수 사용 및 구조화

function test(fruit, quantity) {
  if (!fruit) return;
  const q = quantity || 1; // if quantity not provided, default to one
 
  console.log(`We have ${q} ${fruit}!`);
}
 
//test results
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!

자바스크립트로 작업할 때 항상 null/undefined값을 확인하고 기본값을 할당 해야 합니다.
q는 기본 함수 매개변수를 할당하여 변수를 제거할 수 있습니다.

function test(fruit, quantity = 1) { // if quantity not provided, default to one
  if (!fruit) return;
  console.log(`We have ${quantity} ${fruit}!`);
}
 
//test results
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!

여기서 만약 fruit이 객체라면?

function test(fruit) { 
  // printing fruit name if value provided
  if (fruit && fruit.name)  {
    console.log (fruit.name);
  } else {
    console.log('unknown');
  }
}
 
//test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple

파라미터가 넘어왔는지 검사하고, 객체에 name이라는 속성이 존재하는지 확인하고 그제서야 객체의 속성을 출력하는 함수입니다.

우리는 과일에서 속성 name만 필요하므로 {name}을 사용하여 매개 변수를 재구성할 수 있으므로 fruit.name 대신 코드에서 변수를 사용하여 name을 사용할 수 있습니다. (비구조화 할당)

// destructing - get name property only
// assign default empty object {}
//{name} = {} : 만약 인자로 undefined나 빈 객체 {}가 전달될 경우를 대비해 기본값을 설정합니다.
function test({name} = {}) {
  console.log (name || 'unknown');
}
 
//test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple

4. switch 문보다 Map / Object Literal 사용하기

색상을 기반으로 과일을 출력하려고 합니다.

function test(color) {
  // use switch case to find fruits in color
  switch (color) {
    case 'red':
      return ['apple', 'strawberry'];
    case 'yellow':
      return ['banana', 'pineapple'];
    case 'purple':
      return ['grape', 'plum'];
    default:
      return [];
  }
}
 
//test results
test(null); // []
test('yellow'); // ['banana', 'pineapple']

더 깨끗한 구문을 사용하여 객체 리터럴을 사용하여 동일한 결과를 얻을 수 있습니다.

// use object literal to find fruits in color
  const fruitColor = {
    red: ['apple', 'strawberry'],
    yellow: ['banana', 'pineapple'],
    purple: ['grape', 'plum']
  };
 
function test(color) {
  return fruitColor[color] || [];
}

또는 Map을 사용하여 동일한 결과를 얻을 수 있습니다. ```js // use Map to find fruits in color const fruitColor = new Map() .set('red', ['apple', 'strawberry']) .set('yellow', ['banana', 'pineapple']) .set('purple', ['grape', 'plum']); function test(color) { return fruitColor.get(color) || []; } ``` Map은 ES2015(es6)부터 사용 가능한 객체 유형으로 키 값 쌍을 저장할 수 있습니다.

(map을 이렇게 밖으로 빼서 전역으로 해준 이유는 함수 안에 넣으면 함수가 실행될때마다 map이 생성되는 연산이 추가가 되어서 성능상 손해입니다.)

5. 전체/부분 기준에 대해 Array.every 및 Array.some 사용

코드 줄을 줄이기 위해 새로운 Javascript 배열 기능을 활용하는 방법에 관한 것입니다.

아래 코드에서는 모든 과일이 빨간색인지 확인하고 싶습니다.

for...of 루프 : for (let f of fruits)는 fruits 배열의 각 요소를 순회하는 반복문입니다. f는 배열의 각 요소를 나타내며, 이 예제에서는 각 과일 객체를 의미합니다.

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
  ];
 
function test() {
  let isAllRed = true;
 
  // condition: all fruits must be red
  for (let f of fruits) {
    if (!isAllRed) break;
    isAllRed = (f.color === 'red');
  }
 
  console.log(isAllRed); // false
}

이 코드를 Array.every을 사용하여 줄일 수 있습니다.
const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
  ];
 
function test() {
  // condition: short way, all fruits must be red
  const isAllRed = fruits.every(f => f.color == 'red');
 
  console.log(isAllRed); // false
}

비슷한 방식으로 Araay.some을 이용하면 빨간 과일이 일부 존재하는지 확인할 수 있습니다.
const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
];

function test() {
  // condition: if any fruit is red
  const isAnyRed = fruits.some(f => f.color == 'red');
 
  console.log(isAnyRed); // true
}

0개의 댓글