LHJ

I'm a FE developer.

6. 흐름제어문(Flow Control Statement) - switch

08 Aug 2020 » codespitz_re

switch

  • switch - Special Label Block
      // for문 다음에 나오는 중괄호는 단문, 중문 각각 경우에 따라 맞게 써준다.
      for (let i=0; i<10; i++) {
          console.log(i);    
      }
        
      // switch 문의 중괄호는 반드시 있어야 한다. 
      // 단문, 중문의 의미가 아니다.
      // 이것은 문법적인 token이다.  
      // 이건 함수의 몸체를 나타내는 것도 아니고 중문을 의미하는 것도 아니다. 
      // 단지 switch의 몸체를 나타내는 전용 토큰일 뿐이다.
      // 이 switch 뒤에 오는 {} 은 스페셜 LABEL BLOCK을 만든다. case1, case2, ..., default를 쓸 수 있는..
      // switch 문 : 특별한 레이블 영역을 선언할 수 있는 공간을 만들어주는 문법이다.
      // 일반 LABEL과 똑같다. 소괄호안에 내용과 case 뒤에 내용을 서로 비교한다는 것 빼곤.
      switch (true) {
          
      }
    
  • Fall Through
    case 뒤에 break 문을 안 쓰면 밑에 case들이 계속해서 실행되는 현상이다.
    이 때문에 switch 문을 과소평가 하는 사람들이 있다.
    하지만 그건 모르는 소리다.
    Label의 기본 특성만 이해해도 이런 소리가 안 나온다.
    Fall Through는 너무나도 당연한 작동인거다.

switch case에서 break를 걸면 어디로 빠져나온다?
Undefined Named Label로 빠져나오게 된다.
switch 문 앞에 Auto Label을 만들어준다고 했으니깐.

switch 문 문법

  • Special Label Block 안에 다른 Label 구문을 쓰면 안된다.
    Special Label Block 안에 쓸 수 있는 Label은 casedefault 뿐이다.

switch 문이 어려운 이유

// switch 문이 어려운 이유
// switch {} 안에 문들을 처리하는 방식이 '언어'마다 다르다.
// 자바스크립트는 위에서 아래로 처리한다.

// 위에서 아래로 처리할 때 순서가 '우선' 조건과 매칭되는 값을 찾는다.
// 아래 예시에선 두번째 줄이 조건에 부합한다.
// 두번째 줄 실행 후, break가 없으므로 세번째 줄 실행
// 즉 a, b가 찍힌다.
switch (true) {
    default: console.log('c');
    case true: console.log('a');
    case false: console.log('b');
}

// switch 문은 정확히 매칭되는 값을 찾는 것 같다. truthy 값도 매칭이 안되는 것 같다.
// 아래는 c만 찍힌다.
switch (true) {
    case 22: console.log('a');
    case false: console.log('b');
    default: console.log('c');
}
temp17:
switch (true) {
    default: console.log('c');
    case true: console.log('a'); break temp17;
    case false: console.log('b');
}

원래 위와 같이 쓰는 것이 ‘정석’이다.
Auto Label 기능 때문에 이 사실은 몰랐을 것이다.

RunTime Switch

자바스크립트의 case 문은 런타임에서 해석한다.
런타임에서 해석하기 때문에 자바스크립트에서는 switch 문을 두 가지 형식으로 쓸 수 있다.

  1. 값에 대한 라우팅 - 정적인 경우 유리(우리가 흔히 알고 있는 switch 문)

      var a = true;
      temp17:
      switch (a) {
          default: console.log('c');
          case true: console.log('a'); break temp17;
          case false: console.log('b');
      }
      console.log('end');
           
     // 아래와 같이 값에 대한 평가를 동적으로 처리해도 됨
     var a = true;
         temp17:
         switch (a) {
             default: console.log('c');
             case f1(a): console.log('a'); break temp17;
             case f2(a): console.log('b');
         }
         console.log('end');
    
  2. 조건 평가에 대한 분기 (chain of responsibility)

      switch (true) {
         case network(): // network에서 승부볼 수 있어? 안되면 아래
         case localCache(): // localChache에서 승부볼 수 있어?
         default: // 안내문..
      }
           
     switch (true) {
        case network() === 'online': 
        case network() === 'wifi': 
        case network() === 'offline': 
        case localCache(): // localChache에서 승부볼 수 있어?
        default: // 안내문..
     }
    

switch 구문이 Run Time에서 실행된다는 이야기는 한 줄씩 실행된다는 이야기이다.

var c = 2;
switch (true) {
    case c++ > 5: console.log(c); break;
    case c++ > 5: console.log(c); break;
    case c++ > 5: console.log(c); break;
    case c++ > 5: console.log(c); break;
    case c++ > 5: console.log(c); break;
    case c++ > 5: console.log(c); break;
}

Run Time에서 실행되기 때문에 c에 영향을 준다.
이는 언어마다 다르다.
Run Time에서 실행되는 자바스크립트에선 이점을 유의하며 switch 문을 작성해야된다.

continue, break

continuebreak는 그냥 쓰일 수 있는 것이 아니라 반드시 블럭 안에서만 쓰일 수 있다.
그리고 continuebreak가 쓰이는 경우는 정확히 세 가지이다.

  1. iteration set
  2. label set
  3. switch set

위 세가지 블럭 안에 들어가 있을 때만 작동한다.
그런데 위에서 말한대로 switch 문의 {}블럭이 아니다.
switch label section이라고 불리는 녀석이다.

그래서 block과는 좀 다른 개념이지만, 여튼 위 세가지 경우에만 continuebreak를 사용할 수 있다.

// 아래는 LABEL은 존재하지만 LABEL block이 존재하지 않는다.
// 따라서 continue와 break를 쓸 방법이 없다.
// 아래와 같은 LABEL은 주석 대신으로 쓸 수는 있다.
a:
const b = 3;

// 아래와 같이 주석 대신해서 쓸 수는 있다.
// LABEL을 활용하면 앞쪽 주석을 달 수 있다.
b: const c = 5;