[모던JS] 017. [기본] while과 for 반복문
while과 for 반복문은 특정한 행위를 계속해서 반복시킬 때 간결하게 작성할 수 있는 문법이다.
while 반복문
while 반복문 기본형
while (condition) {
// 반복할 코드
}
condition(조건)이 참이면 반복할 코드가 실행된다.
while 반복문 예제
let i = 0;
while (i < 3) {
console.log(i);
i++;
}
// 0
// 1
// 2
코드 해석
- 최초 i는 0으로 할당한다.
- while 반복문의 condition이 실행된다. i는 0이고 3보다 작으니 true이다. true이니 반복문 body의 코드가 실행된다.
- console에 i의 현재 값인 0이 출력된다.
- i를 1단계 증가시키고 후위 증가 연산자를 사용하여 i를 1 증가시킨다. 후위 증가 연산자는 증가시킨 값을 바로 반환하진 않지만 이 코드에서는 전위형이든 후위형이든 차이가 없다. 코드 밖에서 i 변수를 선언했기 때문에 다음 반복부터 바로 증가된 i 값이 적용된다.
- i는 1이다... 이렇게 반복하다 i가 3이 되는 순간 falst가 되므로 반복문 body가 실행되지 않는다.
만약 위 코드에서 증가 연산자 ++가 사용되지 않았다면 코드는 무한반복된다. 이를 방지하기 위해 아래와 같이 코드를 작성할 수도 있다.
let i = 2;
while (i) {
console.log(i);
i--;
}
// 2
// 1
// i가 0이 되면 0은 falsy한 값이기에 반복문 body가 실행되지 않는다.
위처럼 반복문 body가 두 줄 이상이 아니라 한 줄이면 중괄호를 생략해도 된다.
let i = 3;
while (i) console.log(i--);
// 3
// 2
// 1
위 코드는 i-- 감소 후위 연산자이기 때문에 값을 바로 반환하지 않는다. 따라서 처음에는 i의 값인 3이 반환된다. 그렇게 반복하다 i가 0이 되면 반복을 중단한다.
do...while 반복문
do...while 반복문은 while 반복문하고 동일하다. 그런데 이 문법을 사용하면 condition, 즉 조건식을 반복문 본문 아래로 내릴 수 있다.
let i = 0;
do {
console.log(i);
i++;
} while( i < 3 );
// 0
// 1
// 2
do...while 문법은 conditon이 truthy인지 아닌지에 상관 없이 본문을 최소한 한 번이라도 실행하고 싶을 때만 사용해야 한다. 대다수의 상황에서는 do...while 문법보다는 while() {} 문법이 적합하다.
for 반복문
for 반복문은 while 반복문 보다 문법적으로 복잡하지만 while 반복문 보다 많이 쓰인다.
for 반복문 기본형
for (begin; condition; step) {
// 반복문 실행할 코드 (body)
}
구성요소 | 실행내용 |
---|---|
begin | 반복문에 진입할 때 한 번만 실행된다. |
condition | 반복문마다 해당 조건이 확인된다. false면 반복문을 멈춘다. |
body | condition이 truthy일 동안 계속 실행된다. |
step | 각 반복의 body가 실행된 이후 실행된다. |
for 반복문 예제
for (let i = 0; i < 3; i++) {
console.log(i);
} // 0, 1, 2
코드 해석
순서를 헷갈리면 안 된다. step은 body가 실행된 후 실행되는 것이다.
- for 반복문에 진입한다.
- let i = 0이 실행된다. 변수 i에 0을 할당한다. 이는 한 번만 실행된다.
- i가 3보다 작은지 평가한다. 다음 반복부터는 이 condition부터 반복 실행된다.
- body로 넘어간다. console.log(i)가 실행된다. 0이 출력된다.
- 소괄호의 step이 실행된다. i를 1 증가시킨다.
- i가 1이된 상태에서 3보다 작은지 평가한다.
- 이런 식으로 반복되다가 i가 3이 되는 순간 body는 실행되지 않고 반복문은 종료된다.
- 즉 콘솔에는 0, 1, 2가 출력된다.
for 반복문의 인라인 변수 선언
- for 반복문안에서 선언된 변수는 반복문 밖에서 접근할 수 없다.
- for 반복문 밖에서 선언된 변수더라도 for 반복문 안에서 접근할 수 있다. 따라서 반복문 밖에서 변수에 대한 접근이 필요하다면 변수 선언을 for 반복문 외부에서 하면 된다.
// 변수 선언을 인라인에서 했을 때
for (let i = 0; i < 3; i++) {
console.log(i);
} // 0, 1, 2
console.log(i); // 에러
// 변수 선언을 외부에서 했을 때
let i = 0;
for (i = 0; i < 3; i++) {
console.log(i);
} // 0, 1, 2
console.log(i); // 3
// i가 3이 되었을 때 반복문은 멈추지만 위 반복문의 결과로 i는 최종적으로 3에서 멈췄다.
for 반복문의 구성 요소 생략
begin과 step은 필요가 없으면 생략할 수 있다. 각 구성요소를 생략은 하더라도 세미콜론은 반드시 넣어주어야 한다. 그래야 남은 것이 condition인지 step인지 구분할 수 있다.
위의 코드 예제에서 변수 선언을 외부했을 때 코드를 보면 이미 반복문 밖에서 let i = 0;이라고 선언했는데 for문 안에서 한 번 더 i의 값을 0으로 할당해줬다. 이 과정은 필요가 없으므로 begin은 생략해도 된다.
let i = 0;
for (; i < 3; i++) {
console.log(i);
} // 0, 1, 2
만약 step도 필요 없다면 생략해도 된다.
let i = 0;
for (; i < 3;) {
console.log(i++);
} // 0, 1, 2
세 개 다 생략할 수도 있지만, condition이 생략되면 반복문을 언제 종료해야 하는지 조건을 걸 수 없기 때문에 무한반복문이 된다.
반복문 빠져 나오기 (break)
반복문은 condition이 falsy한 값이 되면 종료된다. 하지만 이 조건과 무관하게 반복문 body에서도 break를 넣어 특정 조건에서 반복문이 종료되도록 설정할 수 있다.
let sum = 0;
while (true) {
let value = +prompt("숫자를 입력하세요.", "");
if (!value) break;
sum += value;
}
alert( '합계' + sum );
위 코드는 모달창을 띄우고 사용자에게 + 단항 연산자를 사용하여 숫자를 입력받는다. 그런데 만약 if value에 ! not 연산자를 넣어 not value가 falsy한 값이면 break;를 넣어 반복문이 더 이상 진행되지 않고 종료되게 하였다.
만약 value가 fasly한 값(즉 0, null, undefined, Nan, '', false)이 아니라면 break를 하지 않고 그 다음 라인의 코드를 실행한다. 복합 할당 연산자 +=를 사용하여 value(사용자가 입력한 숫자)에 sum(0)을 더해서 sum에 할당하도록 했다. (복합 할당 연산자는 좌항과 우항을 더해 그 값을 좌항에 할당한다.)
그리고 alert 창을 띄워 sum의 값을 보여주도록 하고 있다. 그런데 여기서는 while 반복문이 사용됐기 때문에 사용자가 입력한 값, 즉 value에 falsy한 값을 넣지 않고 0이 아닌 숫자를 입력하면 반복문 밖으로 빠져 나가 alert를 실행하지 않고 break만 안 할 뿐이지 계속 반복한다. 즉 숫자를 넣는대로 계속 sum에 할당해두고 이것에 새로 입력한 value를 더해서 value를 더한 누적이 sum이 되게끔 계산기처럼 만든 코드이다.
다음 반복문으로 넘어가기 (continue)
continue 지시자는 break 지시자의 가벼운 버전이다.
break 지시자는 조건식이 true면 반복문 자체를 종료시켜 버리지만 continue 지시자는 반복문 자체를 종료하진 않고 지금 실행 중인 이터레이션을 멈추고 반복문이 다음 이터레이션을 실행시키도록 한다.
이터레이션: 반복문이 한 번 실행되는 사이클, 단위를 말함.
for (let i = 0; i < 10; i++) {
if (i % 2 == 0) continue;
console.log(i);
} // 1, 3, 5, 7, 9
코드 해석
- begin으로 i라는 변수에 0을 할당했다. 이는 for문에서 최초 한 번만 실행된다.
- condition으로 와서 i가 10보다 작은지 확인한다. true이므로 반복문 body로 넘어간다.
- body에서 if의 조건식을 보니 i를 2로 나누었을 때 0인지 확인하고 있다. 즉 짝수인지 확인한다. 만약 짝수라면 truty한 값이 되어 continue를 실행하게 된다. 0은 짝수이므로 continue 지시자가 실행된다. 즉 이 다음 라인 코드들을 실행하진 않고 반복문의 step(i++)을 실행시킨 후 다시 condition을 확인하며 반복된다.
- i가 1이 되고 다시 확인한다... 이 과정을 i가 10이 되는 순간 멈추게 된다.
- 즉 이 과정을 반복하다 보면 결국 console.log(i)까지 가는 숫자는 홀수들만 남게 된다.
continue 지시자와 삼항 연산자(?) 혼용 불가
삼항 연산자(?)는 if를 대체할 수 있다고 했다. 하지만 삼항 연산자를 if문 대용으로 사용하면 직관적이지 않아 코드 가독성이 떨어지기 때문에 삼항 연산자를 if 대체용으로는 사용하지 않는 것이 좋다고 했다.
복습하자면 삼항 연산자는
condition ? value1 : value2
형태로 사용하고, condition이 참이면 value1을, 거짓이면 value2를 반환하는 연산자이다.
그런데 이는 if...else와 동작 순서가 같기 때문에 if...else로 대체해서 사용할 수도 있지만 가독성의 이유로 권장하지 않는다고 했다.
let max = (a > b) ? a : b;
위 코드처럼 간단한 표현에만 사용한다. 위 코드를 풀어보자면 (a > b) 비교를 해서 a가 b보다 크다면 a를 반환하고 아니면 b를 반환하도록 되어 있다. a와 b를 비교해서 더 큰 값을 max라는 변수에 할당하는 코드이다. 참고로 condition을 소괄호로 묶은 것은 안 묶어도 되지만 어디까지가 condition인지 한 눈에 보기 위해 가독성 차원에서 권장하는 사항이다.
본론으로 와 아래와 같이 삼항 연산자와 continue는 같이 사용할 수 없다. if문은 가능하다. 삼항 연산자를 if문 대용으로 사용하면 side effect를 발생시키기에 대용으로 사용하지 말아야 할 이유가 하나 더 생겼다.
// 바른 예시
if (i > 5) {
console.log(i);
} else {
continue;
}
// 바르지 못한 예시
(i < 5) ? console.log(i) : continue; // 에러
break와 continue의 레이블
break와 continue는 반복문 body 안에서 사용하는데, 그 반복문에서만 작동한다. 즉 반복문을 여러번 중첩해서 사용하는 경우 가장 바깥에 있는 반복문과 안쪽의 반복문의 body가 서로 다른 영역이기 때문에 만약 개발자가 반복문 자체를 종료시켜 버리거나 continue로 넘기고 싶은 경우, break나 countinue가 쓰인 반복문에서만 작동하기 때문에 반복문에 이름(레이블)을 붙여서 그 반복문에 대해서 break하거나 continue하라고 지정할 수 있다.
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let input = prompt(`(${i},${j})의 값`, '');
// 사용자가 아무것도 입력하지 않거나 Cancel 버튼을 누르면 두 반복문 모두를 빠져 나온다.
if (!input) break outer; // (*)
// 입력받은 값을 가지고 무언가를 함
}
}
alert('완료!');
위의 코드를 살펴보면 가장 바깥의 for문에 outer: 라는 레이블을 붙였다. 따라서 안쪽의 for문에서 break가 걸려있다고 하더라도 (break 레이블) 형태로 그 레이블 자체를 종료시켜버릴 수 있다.
레이블명은 위 처럼 반복문 앞에 써주어도 되고 다른 라인으로 작성해도 되지만, break나 continue보다 아래에서 레이블을 다는 것은 불가능하다.
outer:
for (let i = 0; i < 3, i++)...
// 가능
break outer;
outer: for (...)
// 불가능
'Programing > JavaScript' 카테고리의 다른 글
[모던JS] 019. [기본] 함수 (함수선언식, 매개변수, 지역변수, 전역변수, return, 함수명명규칙), (0) | 2024.03.28 |
---|---|
[모던JS] 018. [기본] switch문 (0) | 2024.03.28 |
[모던JS] 016. [기본] nullish 병합 연산자 (0) | 2024.03.28 |
015. [기본] 논리 연산자(or &&, !not, 논리 연산자 우선순위) (0) | 2024.03.28 |
[모던JS] 014. [기본] if와 물음표를 사용한 조건 처리(삼항 연산자, 물음표 연산자, 조건부 연산자) (0) | 2024.03.25 |
댓글