반복문 — 같은 일을 백 번 시킨다
Article
1부터 100까지 더하라고 하면 어떻게 할까. 1 + 2 + 3 + ...을 손으로 다 쓸 수는 없다.
컴퓨터가 사람보다 압도적으로 잘하는 일이 바로 이것이다. 지치지 않고 같은 일을 반복하기. 그 명령이 반복문이다.
for — 몇 번 반복할지 알 때
가장 많이 쓰는 반복문이다. 괄호 안에 세 가지를 세미콜론으로 구분해 넣는다.
for (let i = 0; i < 3; i++) {
console.log(`${i}번째`);
}
- 0번째
- 1번째
- 2번째
세 자리가 각각 무슨 일을 하는지 뜯어본다.
- let i = 0초기화 — 딱 한 번
- i < 3조건 — 매번 검사
- i++증감 — 본문 뒤에
실행 순서가 직관과 조금 다르다. 증감식은 본문을 실행한 뒤에 돌아간다.
- 01
초기화 — 한 번만
i를0으로 만든다. 반복하는 동안 다시 실행되지 않는다.let i = 0; - 02
조건 검사
0 < 3은 참이다. 본문으로 들어간다.i < 3 → true - 03
본문 실행
0번째를 출력한다.console.log(`${i}번째`); - 04
증감
이제야
i가1이 된다. 그리고 2번으로 돌아가 조건을 다시 검사한다.i++ → i 는 1 - 05
조건이 거짓이 되면 끝
i가3이 되면3 < 3이 거짓이라 본문에 들어가지 않고 반복이 끝난다.
그래서 i는 0, 1, 2까지만 쓰이고 3에서는 본문이 실행되지 않는다. i < 3이면 세 번 돈다.
0부터 세는 이유
i = 0으로 시작하는 게 어색할 수 있다. 하지만 5강에서 본 것처럼 인덱스가 0부터 시작하므로, 배열과 짝을 맞추면 자연스러워진다.
const fruits = ["사과", "바나나", "포도"];
for (let i = 0; i < fruits.length; i++) {
console.log(i, fruits[i]);
}
- 0 '사과'
- 1 '바나나'
- 2 '포도'
fruits.length가 3이고 마지막 인덱스는 2다. i < fruits.length라고 쓰면 정확히 맞아떨어진다. i <= fruits.length라고 쓰면 마지막에 fruits[3]을 읽어 undefined가 나온다.
값을 쌓아간다
반복문 바깥에 변수를 두고 안에서 더하는 패턴이 기본이다.
let total = 0;
for (let i = 1; i <= 100; i++) {
total += i;
}
console.log(total);
- 5050
total을 밖에 선언한 게 중요하다. 안에 선언하면 매 회차마다 새로 만들어져 값이 쌓이지 않는다.
구구단도 같은 방식이다.
const dan = 2;
for (let i = 1; i <= 5; i++) {
console.log(`${dan} × ${i} = ${dan * i}`);
}
while — 몇 번일지 모를 때
조건이 참인 동안 계속 돈다. 횟수가 정해져 있지 않을 때 쓴다.
let count = 3;
while (count > 0) {
console.log(count);
count--;
}
console.log("발사");
- 3
- 2
- 1
- 발사
for와 달리 초기화와 증감을 직접 챙겨야 한다. count--를 빠뜨리면 조건이 영원히 참이라 프로그램이 멈추지 않는다.
do...while도 있다. 조건을 나중에 검사하므로 본문이 최소 한 번은 실행된다.
let n = 10;
do {
console.log("한 번은 실행된다");
} while (n < 5);
- 한 번은 실행된다
10 < 5는 거짓이지만 이미 본문을 지나온 뒤다. 쓸 일은 드물다.
break — 반복을 즉시 끝낸다
원하는 걸 찾으면 더 돌 이유가 없다.
const numbers = [3, 7, 12, 5, 20];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] > 10) {
console.log("10보다 큰 첫 값:", numbers[i]);
break;
}
console.log("검사 중:", numbers[i]);
}
- 검사 중: 3
- 검사 중: 7
- 10보다 큰 첫 값: 12
12를 찾자마자 빠져나와서 5와 20은 검사하지 않았다. 배열이 길수록 이득이 커진다.
continue — 이번 회차만 건너뛴다
break가 반복을 끝낸다면, continue는 이번 회차만 포기하고 다음으로 넘어간다.
for (let i = 1; i <= 5; i++) {
if (i % 2 === 0) continue;
console.log(i);
}
- 1
- 3
- 5
짝수를 만나면 console.log를 건너뛴다. 5강에서 본 나머지 연산자 %가 여기서 쓰인다.
break
반복문을 탈출
- 다음 회차가 아예 없다
- 반복문 뒤 코드로 이동
- "찾았으니 그만"
continue
이번 회차만 건너뜀
- 반복은 계속된다
- 증감식으로 이동
- "이건 넘어가고 다음"
배열을 도는 더 쉬운 방법
인덱스가 필요 없다면 for...of가 훨씬 읽기 좋다.
const fruits = ["사과", "바나나", "포도"];
for (const fruit of fruits) {
console.log(fruit);
}
- 사과
- 바나나
- 포도
i도, length도, fruits[i]도 없다. 실수할 여지가 줄어든다.
정리하면
for는(초기화; 조건; 증감)세 자리로 이루어지고, 증감은 본문 뒤에 실행된다.- 배열을 돌 때는
i < arr.length라고 쓴다.<=를 쓰면 마지막에undefined를 읽는다. while은 조건을 거짓으로 만드는 코드를 본문에 직접 넣어야 한다. 없으면 무한 루프다.break는 반복을 끝내고,continue는 이번 회차만 건너뛴다.- 인덱스가 필요 없다면
for...of가 더 안전하고 읽기 좋다.
Part 3이 끝났다. 다음 강의부터는 함수다. 지금까지 쓴 코드를 이름 붙여 묶고, 필요할 때 꺼내 쓰는 법을 배운다.