[모던 자바스크립트 Deep Dive] 8장 제어문

J·2023년 6월 27일
0
post-thumbnail

제어문은 조건에 따라 코드 블록을 실행(조건문)하거나 반복 실행(반복문)할 때 사용. 제어문을 사용하면 코드의 실행 흐름을 인위적으로 제어할 수 있음.


블록문 block statement

// 블록문
{
  var foo = 10;
}

// 제어문
var x = 1;
if (x < 10) {
  x++;
}

// 함수 선언문
function sum(a, b) {
  return a + b;
}
  • 0개 이상의 문을 중괄호로 묶은 것으로, 코드 블록 또는 블록이라고 부르기도 함. 자바스크립트는 블록문을 하나의 실행 단위로 취급, 단독으로 사용할 수도 있으나 일반적으로 제어문이나 함수를 정의할 때 사용하는 것이 일반적임.
  • 문의 끝에는 세미콜론을 붙이는 것이 일반적이나 블록문은 언제나 문의 종료를 의미하는 자체 종결성을 갖기 때문에 끝에 세미콜론을 붙이지 않음.

조건문 conditional statement

  • 주어진 조건식의 평과 결과에 따라 코드 블록(블록문)의 실행을 결정함. 불리언 값으로 평가될 수 있는 표현식. if … else문과 switch 문의 두 가지 조건문이 있음.
  • if … else 문
    var num = 2;
    var kind;
    
    // if 문
    if (num > 0) {
      kind = '양수'; // 음수를 구별할 수 없다
    }
    console.log(kind); // 양수
    
    // if...else 문
    if (num > 0) {
      kind = '양수';
    } else {
      kind = '음수'; // 0은 음수가 아니다.
    }
    console.log(kind); // 양수
    
    // if...else if 문
    if (num > 0) {
      kind = '양수';
    } else if (num < 0) {
      kind = '음수';
    } else {
      kind = '영';
    }
    console.log(kind); // 양수
    • 조건식(불리언 값으로 평가될 수 있는 표현식)의 평가 결과, 즉 논리척 참 또는 거짓에 따라 실행할 코드 블록을 결정함. 조건식의 평가 결고가 true일 경우 if 문의 코드 블록을, false일 경우 else 문의 코드 블록이 실행됨.
    • if 문의 조건식은 불리언 값으로 평가되어야 함. 만약 if 문의 조건식이 불리언 값이 아닌 값으로 평가되면 자바스크립트 엔진에 의해 암묵적으로 불리언 값으로 강제 변환되어 실행할 코드 블록 결정.
    • 조건식을 추가하여 조건에 따라 실행될 코드 블록을 늘리고 싶으면 else if 문 사용. else if 문과 else 문은 옵션. if 문과 else 문은 2번 이상 사용할 수 없지만 else if 문은 여러 사용 가능.
    • 대부분의 if … else 문은 삼항 조건 연산자로 바꿔 쓸 수 있음.
  • switch 문
    // 월을 영어로 변환한다. (11 → 'November')
    var month = 11;
    var monthName;
    
    switch (month) {
      case 1:
        monthName = 'January';
      case 2:
        monthName = 'February';
      case 3:
        monthName = 'March';
      case 4:
        monthName = 'April';
      case 5:
        monthName = 'May';
      case 6:
        monthName = 'June';
      case 7:
        monthName = 'July';
      case 8:
        monthName = 'August';
      case 9:
        monthName = 'September';
      case 10:
        monthName = 'October';
      case 11:
        monthName = 'November';
      case 12:
        monthName = 'December';
      default:
        monthName = 'Invalid month';
    }
    
    console.log(monthName); // Output: Invalid month
    • 주어진 표현식을 평가하여 그 값과 일치하는 표현식을 갖는 case 문으로 실행 흐름을 옮김. 표현식과 일치하는 case 문이 없다면 실행 순서는 default 문으로 이동. default 문은 선택 사항으로, 사용할 수도 있고 사용하지 않을 수도 있음.
    • if … else 문의 조건식은 불리언 값으로 평가되어야 하지만 switch 문의 표현식은 불리언 값보다는 문자열이나 숫자 값인 경우가 많음. if … else 문은 논리적 참, 거짓으로 실행할 코드 블록을 결정. switch 문은 논리적 참, 거짓보다는 다양한 상황에 따라 실행할 코드 블록을 결정할 때 사용.
    • 위 예제를 실행해보면 ‘November’가 출력되지 않고 'Invalid month’가 출력됨. 이는 switch 문이 끝날 때까지 이후의 모든 case 문과 default 문을 실행했기 때문. 이를 fall through라 함. monthName 변수에 ‘November’가 할당된 후 switch 문을 탈출하지 않고 연이어 ‘December’가 재할당되고 마지막으로 'Invalid month'가 재할당된 것. 올바른 switch 문은 해당하는 문의 마지막에 break 문을 사용해야 함.
      // 월을 영어로 변환한다. (11 → 'November')
      var month = 11;
      var monthName;
      
      switch (month) {
        case 1:
          monthName = 'January';
          break;
        case 2:
          monthName = 'February';
          break;
        case 3:
          monthName = 'March';
          break;
        case 4:
          monthName = 'April';
          break;
        case 5:
          monthName = 'May';
          break;
        case 6:
          monthName = 'June';
          break;
        case 7:
          monthName = 'July';
          break;
        case 8:
          monthName = 'August';
          break;
        case 9:
          monthName = 'September';
          break;
        case 10:
          monthName = 'October';
          break;
        case 11:
          monthName = 'November';
          break;
        case 12:
          monthName = 'December';
          break;
        default:
          monthName = 'Invalid month';
          break;
      }
      
      console.log(monthName); // Output: November
    • 하지만 아래 예제처럼 break 문을 생략한 폴스루를 활용할 수도 있음.
      var year = 2000; // 2000년은 윤년으로 2월이 29일이다.
      var month = 2;
      var days = 0;
      
      switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
          days = 31;
          break;
        case 4:
        case 6:
        case 9:
        case 11:
          days = 30;
          break;
        case 2:
          // 윤년 계산 알고리즘
          // 1. 연도가 4로 나누어떨어지는 해(2000, 2004, 2008, 2012, 2016, 2020...)는 윤년이다.
          // 2. 연도가 4로 나누어떨어지더라도 연도가 100으로 나누어떨어지는 해(2000, 2100, 2200...)는 평년이다.
          // 3. 연도가 400으로 나누어떨어지는 해(2000, 2400, 2800...)는 윤년이다.
          days = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0 ? 29 : 28;
          break;
        default:
          console.log('Invalid month');
      }
      
      console.log(days); // Output: 29

반복문 loop statement

  • 조건식의 평가 결과가 참인 경우 코드 블록을 실행. 그 후 조건식을 다시 평가하여 여전히 참인 경우 코드 블록을 다시 실행. 이는 조건식이 거짓일 때까지 반복.

  • for문

    for(변수 선언문 또는 할당문; 조건식; 증감식){
        조건식이 참인 경우 반복 실행될 문;
    }
    
    for (var i = 0; i < 2; i++) {
      console.log(i);
    }
    // Output:
    0
    1
    • 조건식이 거짓으로 평가될 때까지 코드 블록 반복 실행.
    • for 문의 변수 선언문, 조건식, 증감식은 모두 옵션이므로 반드시 사용할 필요는 없지만 어떤 식도 선언하지 않으면 무한루프가 됨.
      // 무한루프
      for (;;) { ... }
    • for 문 내 for 문 중첩 사용 가능. 아래 예제는 두 개의 주사위를 던졌을 때 두 눈의 합이 6이 되는 모든 경우의 수를 출력하기 위해 이중 중첩 for 문을 사용한 예.
      for (var i = 1; i <= 6; i++) {
        for (var j = 1; j <= 6; j++) {
          if (i + j === 6) console.log(`[${i}, ${j}]`);
        }
      }
      
      // Output:
      // [1, 5]
      // [2, 4]
      // [3, 3]
      // [4, 2]
      // [5, 1]
  • while 문

    var count = 0;
    
    // count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
    while (count < 3) {
      console.log(count); // 0 1 2
      count++;
    }
    • 주어진 조건식의 평가 결과가 참이면 코드 블록을 계속해서 반복 실행. for 문은 반복 횟수가 명확할 때 주로 사용하고 while 문은 반복 횟수가 불명확할 때 주로 사용.
    • 조건식의 평가 결과가 언제나 참이면 무한루프가 됨.
      // 무한루프
      while (true) { ... }
    • 이를 탈출하려면 코드 블록 내에 if 문으로 탈출 조건을 만들고 break 문으로 코드 블록을 탈출,
      var count = 0;
      
      // 무한루프
      while (true) {
        console.log(count);
        count++;
        // count가 3이면 코드 블록을 탈출한다.
        if (count === 3) break;
      } // 0 1 2
  • do … while 문

    var count = 0;
    
    // count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
    do {
      console.log(count);
      count++;
    } while (count < 3); // 0 1 2
    • 코드 블록을 먼저 실행하고 조건식을 평가. 따라서 코드 블록은 무조건 한 번 이상 실행됨.

break 문

  • swtich 문과 while 문에서 살펴보았듯 break 문은 코드 블록을 탈출함. 좀 더 정확히 표현하자면 코드 블록을 탈출하는 것이 아니라 레이블 문, 반복문 또는 switch 문의 코드 블록을 탈출함. 이 외 코드 블록에 break 문을 사용하면 SyntaxError 발생함.
    if (true) {
      break; // Uncaught SyntaxError: Illegal break statement
    }
  • 레이블 문이란? 식별자가 붙은 문.
    // foo라는 레이블 식별자가 붙은 레이블 문
    foo: console.log('foo');
    // foo라는 식별자가 붙은 레이블 블록문
    foo: {
      console.log(1);
      break foo; // foo 레이블 블록문을 탈출한다.
      console.log(2);
    }
    
    console.log('Done!');
    // outer라는 식별자가 붙은 레이블 for 문
    outer: for (var i = 0; i < 3; i++) {
      for (var j = 0; j < 3; j++) {
        // i + j === 3이면 outer라는 식별자가 붙은 레이블 for 문을 탈출한다.
        if (i + j === 3) break outer;
        console.log(`inner [${i}, ${j}]`);
      }
    }
    
    console.log('Done!');
    • 중첩된 for 문 외부로 탈출할 때 유용하지만 그 밖의 경우에는 일반적으로 권장하지 않음. 프로그램의 흐름이 복잡해져 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문.

continue 문

  • 반복문의 코드 블록을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동시킴. break 문처럼 반복문을 탈출하지는 않음.
  • 특정 문자의 개수를 세는 예.
    var string = 'Hello World.';
    var search = 'l';
    var count = 0;
    
    // 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
    for (var i = 0; i < string.length; i++) {
      // 'l'이 아니면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
      if (string[i] !== search) continue;
      count++; // continue 문이 실행되면 이 문은 실행되지 않는다.
    }
    
    console.log(count); // 3
    
    // 참고로 String.prototype.match 메서드를 사용해도 같은 동작을 한다.
    const regexp = new RegExp(search, 'g');
    console.log(string.match(regexp).length); // 3
    // continue 문을 사용하지 않으면 if 문 내에 코드를 작성해야 한다.
    for (var i = 0; i < string.length; i++) {
      // 'l'이면 카운트를 증가시킨다.
      if (string[i] === search) {
        count++;
        // code
        // code
        // code
      }
    }
    
    // continue 문을 사용하면 if 문 밖에 코드를 작성할 수 있다.
    for (var i = 0; i < string.length; i++) {
      // 'l'이 아니면 카운트를 증가시키지 않는다.
      if (string[i] !== search) continue;
    
      count++;
      // code
      // code
      // code
    }

본 포스팅은 모던 자바스크립트 Deep Dive를 공부하며 복습을 위해 정리한 내용임.
profile
벨로그로 이사 중

0개의 댓글