제어문 (Control Flow Statements)
개요
제어문이란
말 그대로 제어문임
코드의 흐름을 인위적으로 제어할 수 있기 때문
하지만 이를 남발하면 코드를 읽기 어려워진다고 한다
그래서 이를 해결할 수단으로 고차 함수를 사용한다고 함
고차함수란 함수를 인자로 받거나 반환하는 함수를 뜻하는데 여기서 설명하는 고차 함수는 forEach, map, filter, reduce를 뜻함
일단은 제어문부터 이해하고 넘어가자
핵심 개념
- 제어문은 코드의 실행 순서를 변경한다
- 위에서 아래로 순차적으로 실행되는 흐름을 제어문으로 변경할 수 있다
블록문 (Block Statement)
제어문을 이해하려면 블록문을 먼저 이해해야 한다
문을 중괄호로 묶은 것으로 그냥 코드블록임
블록문도 자체 종결성을 갖기 때문에 블록문의 끝에는 세미콜론을 붙이지 않음
주로 제어문에서 조건에 따라 분기처리 되어 실행되는 부분을 담당함
// 블록문
{
var foo = 10;
}
조건문 (Conditional Statement)
if...else 문
if...else 문은 주어진 조건식(불리언 값으로 평가될 수 있는 표현식)의 평가 결과, 즉 논리적 참(true) 또는 거짓에 따라 실행할 코드블록을 결정함
이때 또 난리가 나는게 if문의 조건식이 불리언이 아닌 값으로 평가되면 암묵적으로 불리언 값으로 강제 변환된다고 한다
암묵적 변환은 어떻게 가능한가
암묵적 변환은 자바스크립트 엔진에 정의된 연산 규칙에 의해 발생한다.
자바스크립트에서 타입은 변수(슬롯)가 아니라 값에 존재한다.
특정 연산이나 문맥(예: +, -, 조건문 등)에 따라 엔진은 ToBoolean, ToString, ToNumber 같은 추상 연산을 적용하여 값을 해당 상황에 맞는 타입으로 변환한 뒤 사용한다.
이때 원래 값이 바뀌는 것이 아니라, 변환된 값이 일시적으로 사용된다.
조건문의 경우에도 동일하게 ToBoolean 규칙이 적용되어 값이 truthy/falsy로 평가된다.자바쟁이였던 나에겐 너무나도 벅업다...
if (조건식1) {
// 조건식1이 참이면 실행
} else if (조건식2) {
// 조건식2가 참이면 실행
} else {
// 위 조건이 모두 거짓이면 실행
}
코드 블록 내의 문이 하나뿐이라면 중괄호를 생략할 수 있다.
이게 가능한 이유는
코드블록은 여러 개의 문을 하나의 문으로 묶어주지만
하나의 문은 이 과정이 필요 없기 때문임
if (조건식1) console.log('배부르다');
else if (조건식2) console.log('하지만 내일은');
else console.log('배고프겠지');
삼항 연산자와 조건문의 가장 큰 차이는 값으로 평가될 수 있는가이다
그리고 가독성이 좋다는데 나는 진짜 몰루겠다...
var nu = 2;
var kind = nu ? (nu > 0 ? '누가 이것좀 해봐' : '없으면 내가 해야지') : '쩝';
console.log('누가 이것좀 해봐');
switch 문
switch문이 진짜 애매한 것 같음
switch 문의 case에는 표현식이 올 수 있지만,
각 case는 switch에 전달된 값과 === 로 비교된다.
따라서 비교 기준이 단순 값 일치에 한정되기 때문에
범위 비교나 복잡한 조건식을 직접 표현하기에는 적합하지 않다.
너무 static해
switch (표현식) {
case 표현식1:
// 실행문
break;
case 표현식2:
// 실행문
break;
default:
// 실행문
}
추가로 fall through 라는 문제가 있는데 처음 실행된 case에서 break를 안걸어주면 그 밑에 있는 코드를 다 실행해버린다고 함
그 덕에 이런 패턴이 가능하다고 함
switch (x) {
case 1:
case 2:
case 3:
console.log("1~3");
break; // 신기함 ㅋㅋ
}
if처럼 조건기반 제어문이 아니라 Jump to 로 넘어가는 개념이라는데 정글에서 배운게 기억이 잘 안나서 정확한 개념을 이해하기 위해 공부해봤다
switch 문은 조건을 순차적으로 평가하는 구조가 아니라,
값에 따라 특정 case의 위치(레이블)로 분기하는 구조이다.
저수준에서는 jump table 또는 비교-분기 형태로 구현되며,
case는 독립적인 블록이 아니라 단순한 실행 위치(label)이기 때문에
break가 없으면 다음 명령으로 자연스럽게 이어지며 fall-through가 발생한다.
sub x, 1 ; index 맞추기
cmp x, 2 ; 범위 체크
ja out_of_range
jmp [jump_table + x * 8]
요런 식으로 jump table로 최적화되는 경우에 한해 switch가 압도적으로 빠름
동시에 fall-through가 발생하는 이유이기도 함
반복문 (Loop Statement)
for 문
'난 for문과 if문만 있으면 모든 걸 만들 수 있어' 의 그 for문이다
for문의 내부동작은 다음과 같음.
for (변수 선언문 또는 할당문; 조건식; 증감식) {
// 조건식이 참인 동안 반복 실행
}
정말 구수한 구조
- 변수 선언 (최초 1회)
- 조건식 평가 → true면 코드블록 실행
- 코드블록 실행 완료 후 증감식 실행
- 다시 조건식 평가 → true면 코드블록 실행
- 코드블록 실행 완료 후 증감식 실행
- ...반복
- 조건식 평가 → false면 종료
즉 조건식 → 코드블록 → 증감식 순서임. 증감식이 먼저 도는게 아니라 코드블록이 먼저 실행된 후에 증감식이 돈다.
while 문
빠른무한
얘는 더 생각하는게 단순함
while (!배부르니) {
밥먹기
배부른가?
}
조건식의 평가 결과가 참이면 한 무 루 프 를 돌려버림
이를 막기 위해 break문을 사용함
do...while 문
do while문은 마치 아침시간의 나같다
일단 5분을 더 자고 지각 각을 살피는 느낌
do {
5분만 더 잠자기
} while (!지각했니)
while문같은 경우 먼저 배부른지 체크하고 배부르면 밥을 먹지 않는다
do while문은 일단 냅다 디비자고 생각함
break 문
break문이 좀 심오함
레이블문, 반복문, switch문에서 탈출한다
근데 이외의 상황에서 쓰면 SyntaxError 뜸
참고로 레이블문은 약간 깃빨 꽂아놓은 거라고 생각하면 된다.
아래 예제에서 살펴보듯 2중 for문이지만 break outer를 수행하면 상위 for문까지 부숴버림
// 레이블 문에서의 break
outer: for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (i + j === 3) break outer;
}
}
근데 되도록이면 이런 패턴은 가독성을 많이 해치기 때문에 사용하지 않는 편이 좋다고 한다
continue 문
continue문은 반복문의 코드블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동시킨다
하지만 break처럼 탈출은 안함
for (var i = 0; i < string.length; i++) {
if (string[i] !== search) continue;
count++;
}
사용하면 가독성이 좋아진다고는 하는데 사용하는 방식에 따라 좀 갈릴듯??
핵심 포인트
- 제어문은 코드의 순차적 실행 흐름을 인위적으로 변경하며, 조건문(if/switch)과 반복문(for/while/do-while), 그리고 break/continue로 구성된다
- switch는 조건 평가가 아닌 값 기반 jump 분기이므로 fall-through가 발생하고, for문은 조건식 → 코드블록 → 증감식 순서로 실행된다
- 제어문의 남용은 가독성을 해치므로 forEach, map, filter, reduce 같은 고차 함수로 대체할 수 있는지 항상 고려하자
참고 자료
- 모던 자바스크립트 Deep Dive 8장
'코딩딩 > Javascript' 카테고리의 다른 글
| 날것 - 객체 리터럴 (0) | 2026.04.08 |
|---|---|
| 날것 - 타입 변환과 단축 평가 (0) | 2026.04.01 |
| 날것 - 연산자 (0) | 2026.03.18 |
| JavaScript 마이크로태스크 큐, 왜 먼저 실행되는 건데? (0) | 2026.03.13 |
| 날것 - 데이터 타입 (0) | 2026.03.11 |