|
| 1 | +# Chapter 08 - 제어문 |
| 2 | +제어문은 조건에 따라 블록 분기를 하거나 반복 실행할 때 사용됩니다. |
| 3 | +일반적으로 코드는 위에서 아래로 순차적으로 진행되지만, |
| 4 | +제어문을 사용하면 코드의 실행 흐름을 인위적으로 제어할 수 있습니다. |
| 5 | + |
| 6 | +하지만 코드의 실행 순서가 변경된다는 것은 단순히 위에서 아래로 순차적으로 진행하는 |
| 7 | +직관적인 코드의 흐름을 혼란스럽게 합니다. |
| 8 | + |
| 9 | +`forEach`, `map`, `filter`, `reduce`와 같은 고차 함수를 사용한 함수형 프로그래밍 기법에서는 |
| 10 | +제어문의 사용을 억제하여 복잡성을 해결하려 노력합니다. |
| 11 | + |
| 12 | + |
| 13 | +<br><br> |
| 14 | + |
| 15 | +### 블록문 |
| 16 | +블록문은 0개 이상의 0개 이상의 문을 중괄호로 묶은 것입니다. |
| 17 | +자바스크립트는 블록을 하나의 실행 단위로 취급합니다. |
| 18 | +블록을 단독으로 사용할 수도 있지만, 일반적으로 제어문이나 함수를 정의할 때 사용하는 것이 일반적입니다. |
| 19 | + |
| 20 | +문의 끝에는 세미콜론(`;`)을 붙이는 것이 일반적이지만, |
| 21 | +블록문은 언제나 문의 종료를 의미하는 자체 종결성을 가지고 있기 때문에 |
| 22 | +블록문의 끝에는 세미콜론을 붙이지 않습니다. |
| 23 | + |
| 24 | +``` js |
| 25 | +// 블록문 |
| 26 | +{ |
| 27 | + let tmp = 10; |
| 28 | +} |
| 29 | + |
| 30 | +// 제어문 |
| 31 | +let tmp = 1; |
| 32 | +if (tmp < 10) { |
| 33 | + x++; |
| 34 | +} |
| 35 | + |
| 36 | +// 함수 선언문 |
| 37 | +function sum(a, b) { |
| 38 | + return a + b; |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +<br><br> |
| 43 | + |
| 44 | +### 조건문 |
| 45 | +조건문은 조건식의 평가 결과에 따라 |
| 46 | +코드 블록의 실행을 결정합니다. |
| 47 | +조건식은 boolean 값으로 평가될 수 있는 표현식입니다. |
| 48 | + |
| 49 | +자바스크립트에서는 `if ... else`, `switch`문이 있다. |
| 50 | + |
| 51 | +<br> |
| 52 | + |
| 53 | +#### if ... else 문 |
| 54 | +`if ... else`문은 주어진 조건식의 평가 결과(참 또는 거짓)에 따라 실행할 코드 블록을 결정합니다. |
| 55 | + |
| 56 | +``` js |
| 57 | +if (조건식) { |
| 58 | + // true일 경우 |
| 59 | +} else { |
| 60 | + // false일 경우 |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +조건식을 추가하여 조건에 따라 실행할 블록을 늘리고 싶다면 `else if` 문을 추가하면 됩니다. |
| 65 | + |
| 66 | +``` js |
| 67 | +if (조건식 1){ |
| 68 | + |
| 69 | +} else if (조건식 2) { |
| 70 | + |
| 71 | +} else { |
| 72 | + |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | +``` js |
| 77 | +let num = 10; |
| 78 | +let kind; |
| 79 | + |
| 80 | +if (num > 0) kind = "양수"; |
| 81 | +else if (num < 0) kind = "음수"; |
| 82 | +else kind = "0" |
| 83 | +``` |
| 84 | + |
| 85 | +<br> |
| 86 | + |
| 87 | +대부분의 `if ... else`문은 삼항 조건 연산자로 변환이 가능합니다. |
| 88 | + |
| 89 | +``` js |
| 90 | +let x = 1; |
| 91 | +let result; |
| 92 | + |
| 93 | +if (x % 2) { |
| 94 | + result = "홀수"; |
| 95 | +} else { |
| 96 | + result = "짝수"; |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +위 예제는 아래와 같이 삼항 조건 연산자로 바꿀 수 있습니다. |
| 101 | + |
| 102 | +``` js |
| 103 | +let x = 1; |
| 104 | + |
| 105 | +let result = x % 2 ? "홀수" : "짝수" |
| 106 | +``` |
| 107 | + |
| 108 | +<br> |
| 109 | + |
| 110 | +만약 경우의 수가 3가지 이상이라면 다음과 같이 바꿔 쓸 수도 있습니다. |
| 111 | + |
| 112 | +``` js |
| 113 | +let num = 1; |
| 114 | +let kind = num ? (num > 0 ? "양수" : "음수") : "0"; |
| 115 | +``` |
| 116 | + |
| 117 | +<br> |
| 118 | + |
| 119 | +조건에 따라 단순히 값을 결정하여 변수에 할당하는 경우에는 삼항 조건 연산자를 사용하는 편이 가독성이 좋지만, |
| 120 | +조건에 따라 실행해야 할 내용이 복잡하여 여러 줄의 문이 필요하다면 `if ... else`를 사용하는 편이 좋습니다. |
| 121 | + |
| 122 | + |
| 123 | +<br><br> |
| 124 | + |
| 125 | +#### switch 문 |
| 126 | +switch 문은 주어진 표현식을 평가하여 그 값과 일치하는 표현식을 갖는 `case` 문으로 실행 흐름을 옮깁니다. |
| 127 | +`case` 문은 상황을 의미하는 표현식을 지정하고 콜론으로 마칩니다. |
| 128 | +그리고 그 뒤에 실행할 문들을 위치시킵니다. |
| 129 | + |
| 130 | +<br> |
| 131 | + |
| 132 | +`switch` 문의 표현식과 일치하는 `case` 문이 없다면 실행 순서는 `default` 문으로 이동합니다. |
| 133 | +`default` 문은 선택 사항으로, 사용할 수도 있고 사용하지 않을 수도 있습니다. |
| 134 | + |
| 135 | +``` js |
| 136 | +switch (표현식) { |
| 137 | + case 표현식 1: |
| 138 | + console.log("표현식 1"); |
| 139 | + break; |
| 140 | + case 표현식 2: |
| 141 | + console.log("표현식 2"); |
| 142 | + break; |
| 143 | + default: |
| 144 | + console.log("default"); |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +`switch` 문의 표현식은 boolean 값 보다는 문자열이나 숫자 값인 경우가 많습니다. |
| 149 | +즉, `switch` 문은 논리적 차모, 거짓 보다는 상황(case)에 따라 실행할 블록을 결정할 때 사용되빈다. |
| 150 | + |
| 151 | + |
| 152 | +<br> |
| 153 | + |
| 154 | +`default`를 제외한각 각 블록에는 `break`를 넣는 것이 일반적이지만, |
| 155 | +아래와 같이 `break`를 넣지 않는 것이 유용한 경우도 있다. |
| 156 | + |
| 157 | +``` js |
| 158 | +let year = 2024; |
| 159 | +let month = 3; |
| 160 | +let days = 15; |
| 161 | + |
| 162 | +switch (month) { |
| 163 | + case 1: case 3: case 5: case 7: case 8: case 10: case 12: |
| 164 | + days = 31; |
| 165 | + break; |
| 166 | + case 4: case 6: case 9: case 11: |
| 167 | + days = 30; |
| 168 | + break; |
| 169 | + case 2: |
| 170 | + days = ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0)) ? 29 : 28; |
| 171 | + break; |
| 172 | + default: |
| 173 | + console.log("잘못 된 month 입니다."); |
| 174 | +} |
| 175 | +``` |
| 176 | + |
| 177 | +C언어를 기반으로 하는 프로그래밍은 대부분 `switch`문을 지원하지만 |
| 178 | +파이썬과 같이 `switch` 문을 지원하지 않는 프로그래밍 언어도 있습니다. |
| 179 | + |
| 180 | +<br><br> |
| 181 | + |
| 182 | +### 반복문 |
| 183 | +반복문은 평가 결과가 참인 경우 코드 블록을 실행합니다. |
| 184 | +그 후 조건식을 다시 평가하여 여전히 참일 경우에 코드 블록을 다시 실행시킵니다. |
| 185 | + |
| 186 | +자바스크립트는 `for`, `while`, `do ... while` 문을 제공합니다. |
| 187 | + |
| 188 | +<br> |
| 189 | + |
| 190 | +#### for 문 |
| 191 | +`for` 문은 조건식이 거짓으로 평가될 때 까지 코드 블록을 반복 실행합니다. |
| 192 | + |
| 193 | +``` js |
| 194 | +for (변수 선언문 또는 할당문; 조건식; 증감식) { |
| 195 | + // 조건식이 참일 경우 실행될 문 |
| 196 | +} |
| 197 | +``` |
| 198 | + |
| 199 | +``` js |
| 200 | +for (let i = 0; i < 12; i++) { |
| 201 | + console.log(i); |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +<br> |
| 206 | + |
| 207 | +`for`문의 변수 선언문, 조건식, 증감식은 모두 옵션이므로 반드시 사용할 필요는 없습니다. |
| 208 | +단, 어떤 식도 선언하지 않으면 무한 루프가 됩니다. |
| 209 | + |
| 210 | +``` js |
| 211 | +// infinity loop |
| 212 | +for (;;) { ... } |
| 213 | +``` |
| 214 | + |
| 215 | +<br> |
| 216 | + |
| 217 | +`for` 문을 중첩해서 사용할 수도 있습니다. |
| 218 | + |
| 219 | +``` js |
| 220 | +for (let i = 0; i < 12; i++) { |
| 221 | + for (let j = 0; j < 12; j++) { |
| 222 | + console.log(i * j); |
| 223 | + } |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +<br><br> |
| 228 | + |
| 229 | +#### while 문 |
| 230 | +`while` 문은 조건식의 평가 결과가 참이면 코드 블록을 반복 실행합니다. |
| 231 | +<font color='orange'>`for` 문은 반복 횟수가 명확할 때 사용하고, `while`문은 반복 횟수가 불명확할 때 주로 사용합니다.</font> |
| 232 | + |
| 233 | +``` js |
| 234 | +let cnt = 0; |
| 235 | + |
| 236 | +while (cnt < 3) { |
| 237 | + console.log(cnt); |
| 238 | + cnt++; |
| 239 | +} |
| 240 | +``` |
| 241 | + |
| 242 | +조건식의 평가 결과가 언제나 참이면 무한 루프가 됩니다. |
| 243 | +무한 루프 탈출을 위해서는 `break` 문을 추가하면 됩니다. |
| 244 | + |
| 245 | +``` js |
| 246 | +while (true) { ... } |
| 247 | +``` |
| 248 | + |
| 249 | +<br><br> |
| 250 | + |
| 251 | +#### do ... while 문 |
| 252 | +`do ... while` 문은 코드 블록을 먼저 실행하고 조건식을 평가합니다. |
| 253 | +따라서 코드 블록은 무조건 한 번 이상 실행됩니다. |
| 254 | + |
| 255 | +``` js |
| 256 | +let cnt = 0; |
| 257 | + |
| 258 | +do { |
| 259 | + console.log(cnt); |
| 260 | + cnt++; |
| 261 | +} while (cnt < 3); |
| 262 | +``` |
| 263 | + |
| 264 | + |
| 265 | +<br><br> |
| 266 | + |
| 267 | +### break 문 |
| 268 | +`break` 문은 `while` 문에서 살펴보았듯이 코드 블록을 탈출합니다. |
| 269 | +정확히는 코드 블록을 탈출하는 것이 아니라, 레이블 문, 반복문 또는 `switch` 문의 코드 블록을 탈출합니다. |
| 270 | + |
| 271 | +> 레이블 문 (label statement) |
| 272 | +> ``` js |
| 273 | +> // foo라는 레이블 식별자가 붙은 레이블 문 |
| 274 | +> foo: console.log('foo'); |
| 275 | +> ``` |
| 276 | +
|
| 277 | +<br> |
| 278 | +
|
| 279 | +레이블 문은 프로그램의 실행 순서를 제어하는 데 사용됩니다. |
| 280 | +`switch` 문의 `case` 문과 `default` 문도 레이블 문입니다. |
| 281 | +
|
| 282 | +``` js |
| 283 | +foo: { |
| 284 | + console.log(1); |
| 285 | + break foo; // foo 레이블 블록문을 탈출 |
| 286 | + console.log(2); |
| 287 | +} |
| 288 | +``` |
| 289 | +
|
| 290 | +<br> |
| 291 | + |
| 292 | +중첩된 `for` 문의 내부 `for` 문에서 break 문을 사용하면 |
| 293 | +내부 `for` 문을 탈출하여 외부 `for` 문으로 진입하게 됩니다. |
| 294 | + |
| 295 | +이때 내부 `for` 문이 아닌 외부 `for` 문을 탈출하려면 레이블 문을 사용하면 됩니다. |
| 296 | + |
| 297 | +``` js |
| 298 | +// 즉시 외부로 탈출 |
| 299 | +outer: for (let i = 0; i < 3; i++) { |
| 300 | + for (let j = 0; j < 3; j++) { |
| 301 | + break outer; |
| 302 | + } |
| 303 | +} |
| 304 | +``` |
| 305 | + |
| 306 | +레이블 문은 중첩 for 문으 외부로 탈출할 때 유용하지만 그 밖의 경우에는 일반적으로 권장하지 않습니다. |
| 307 | +레이블 문을 사용하면 프로그램의 흐름이 복잡해져서 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문이다. |
| 308 | + |
| 309 | +<br><br> |
| 310 | + |
| 311 | +### continue 문 |
| 312 | +`continue` 문은 반복문의 코드 블록 실행을 현 시점에서 중단하고 |
| 313 | +반복문의 증감식으로 실행 흐름을 이동시킵니다. |
| 314 | + |
| 315 | +아래 코드는 특정 문자의 수를 세는 예입니다. |
| 316 | +``` js |
| 317 | +let string = "hello world"; |
| 318 | +let search = "l"; |
| 319 | +let cnt = 0; |
| 320 | + |
| 321 | +for (let i = 0; i < string.length; i++) { |
| 322 | + if (string[i] !== search) continue; |
| 323 | + cnt++; |
| 324 | +} |
| 325 | +``` |
| 326 | + |
| 327 | +위 예제의 for 문은 아래와 동일하게 동작한다. |
| 328 | + |
| 329 | +``` js |
| 330 | +for (let i = 0; i < string.length; i++) { |
| 331 | + if (string[i] === string) count ++; |
| 332 | +} |
| 333 | +``` |
| 334 | + |
| 335 | +if 문 내에서 실행해야 할 코드가 한 줄이라면 `continue` 문을 사용했을 때보다 간편하고 가독성이 좋다. |
| 336 | +하지만 `if` 문 내에서 실행해야 할 코드가 길다면 |
| 337 | +들여쓰기가 한 단계 더 깊어지므로 `continue` 문을 사용하는 편이 더 좋다. |
| 338 | + |
| 339 | +<br><br> |
0 commit comments