제어문
- 조건에 따라 코드를 특정조건에 따라 실행하거나, 반복 실행할 때 사용
- 일반적으로 코드는 위에서 아래방향 으로 순차실행
동기방식 이지만 제어문을 사용하면 코드의 실행순서를 인위적으로 제어가능 - 과도힌 제어문의 사용은 코드의 흐름을 이해하기 어렵게 만든다
(개인적인의견으로는 어쩔수없다고 생각합니다
충분히 다른 forEach, map, filter ,reduce 로 대체가 가능한 상황이있을수있지만
그렇지 않은상황에서 덕지덕지 제어문을 사용해도 나쁘지는 않다고생각합니다)
블록문
- 0개 이상의 문을 중괄호로 묶은것
(진짜 이해하기 어렵게 설명해놓은것 같습니다
쉽게말해 0개 이상의 코드구문을 중괄호로 감싼것 이라고 생각하는게 좀더 편할거같습니다) - JS는 블록문을 하나의 실행 단위로 취급
단독으로도 사용가능하지만, 제어문이나 함수를 정의할때 주로 사용됩니다 - 코드구문 끝에는 ; 을 붙여서 종료를 나타내지만
블록문은 {} 중괄호라는 코드구문의 종료를 뜻하는 자체종결성을 갖기 때문에
블록문 끝에는 ;을 붙이지 않는다
// 블록문
{
let foo = 10;
}
// 제어문
let x = 1;
if(x < 10) {
x++;
}
// 함수 선언문
function sum(a , b) {
return a+b
}
진짜 조건문
- 말그대로 특정 조건이 참이면 그해당 구문의 코드를 실행시킨다라고 축약시킬수있습니다
- 논리적으로 참이거나 거짓일 경우에 따라 실행할 코드를 적는다 라고 생각할수있습니다
- if....else 문과 switch 문 두가지의 조건문을 제공하고있습니다
if...else
이라고 생각하면 조금더 쉬울거같다고 생각이듭니다
if (조건식) {
// if 조건식이 참이면 해당 코드블록이 실행
} else {
// else 조건식이 참이면 해당코드블록이 실행
}
if 문의 조건식은 불리언값으로 값이 나와야만합니다
만약 if 문의 조건식이 불리언 값이 아닌 값으로 나온다면
JS엔진에 의해 암묵적으로 강제적으로 불리언 값으로 변환되어
실행할 코드 블록을 결정합니다조건식을 추가하여 여러 조건에 따라 실행될 코드 블록을 늘리고 싶다면 else if 문을 사용가능
if (조건식) {
// if 조건식이 참이면 해당 코드블록이 실행
} else if (조건식2) {
// else 조건식2가 참이면 해당코드블록이 실행
} else {
// 조건식 1,2 가 모두 거짓이면 해당 코드블록이 실행
}
- else if 문과 else 문은 모두다 옵션입니다
실제로 사용해도 되고 안해도 됩니다
if 와 else 는 2번이상 사용할수없지만
else if 는 여러번 사용 가능합니다
let num = 2;
let kind
// if 문
if (num > 0) {
kind = '양수'; // 음수를 구별 불가
}
console.log(kind)
// if ..else
if (num > 0 ) {
kind = '양수';
} else {
kind = '음수'
}
console.log(kind)
// if ...else if
if(num > 0) {
kind = '양수';
} else if (num < 0) {
kind = '음수';
} else {
kind = '0'
}
console.log(kind)
만약 코드블록내의 구문이 하나라면 중괄호 생략가능
if (true) console.log(123)
// 이것또한 동작합니다
하지만 else if 문까지 있는경우에 조건문이 점점 복잡해진다면 중괄호로 구문의 끝을 나타내지않는다면
유지보수과정에서 인간적인 오류가 생길수도있다고 생각합니다
단순한 조건문에서는 사용해도 되지만
점점 많아지는 조건문에서는 중괄호를 사용하는게 맞다고 생각합니다
삼항연산자를 사용해서도 표현이 가능하다
// if ..else
if (num > 0 ) {
kind = '양수';
} else {
kind = '음수'
}
console.log(kind)
와 같은 예제를
let result = num > 0 ? '양수' : '음수'
// if ...else if
if(num > 0) {
kind = '양수';
} else if (num < 0) {
kind = '음수';
} else {
kind = '0'
}
console.log(kind)
와 같은예제도
let result = num ? ( num > 0 ? '양수' : '음수') : '0'
하지만 밑에 삼항연사자 예제는 사실상
삼항연산자 안에 삼항연산자가 잇다고 생각할수잇음
2개의 삼항연산자가 존재하는경우
개인적인 생각으로나 리뷰 를 받다보면 if..else 에서만 삼항연산자를 사용하는게
깔끔하다고 생각합니다
switch 문
- switch 는 주어진 표현식을 평가하여
그값과 일치하는 값을 갖는 case 문으로 실행 순서를 바꾼다
case 문은 상황의 의미하는 표현식을 지정하고 콜론으로 마침표를 찍어준다
그리고 그뒤에 실행할 코드구문을 위치 시킨다 - switch 문의 표현식과 일치하는 case 문이 없다면
실행순서는 default 문으로 이동
default 문은 선택사항으로 사용하기도 하고 안하기도 한다
switch(표현식) {
case 표현식1;
switch 의 표현식과 표현식1이 일치하면 실행될 구문
break;
case 표현식2;
switch 의 표현식과 표현식2와 일치하면 실행될 구문
break;
default:
switch 의 표현식과 일치하는 case 문이 없을 때 실행될 구문
}
- if...else 문의 조건식은 참과 거짓 불리언 값으로 평가되어야하지만
switch 문 표현식은 불리언 값보다는
문자열이나 숫자인 경우가 많다 - 고로 생각해본다면 if...else 는 논리적으로 참, 거짓으로 실행할 코드를 결정하고
switch 는 논리적인 참,거짓 보다는 좀더 다양한상황에 따라 실행할 코드를 결정한다
// 월을 영어로 변환한다. (11 → 'November')
var month = 11;
var monthName;
switch (month) {
case 1:
monthName = 'January';
case 2:
monthName = 'February';
case 3:
monthName = 'March';
case 4:
monthName = 'April';
case 5:
monthName = 'May';
case 6:
monthName = 'June';
case 7:
monthName = 'July';
case 8:
monthName = 'August';
case 9:
monthName = 'September';
case 10:
monthName = 'October';
case 11:
monthName = 'November';
case 12:
monthName = 'December';
default:
monthName = 'Invalid month';
}
console.log(monthName); // Invalid month
여기서 잠깐쓰으으으으으
실제로 해당예제를 실행시켜보면 Invalid month 가 실행된다
왜냐하면 case문에 따라 코드구문 순서가 변경은되었지만
코드구문을 실행하고나서 탈출하지못하고
계속 반복해서 switch 문이 끝날때까지 저 예제 안에서 머물었기 때문이다
이와 같은 경우를 폴스루 라고한다
실제로 november 가 할당되었지만
끝나지않고 다음 case인 december 가 재할당되었고
그러고 나서도 탈출을 못해서
마지막 default case 까지 나와서 종료가 된상황
- 이러한 폴스루 현상을 방지하기위해서는
case 코드구문 마지막에 break 를 사용해주어야만한다 - break는 코드블록에서 탈출하는 역할을해준다
// 월을 영어로 변환한다. (11 → 'November')
var month = 11;
var monthName;
switch (month) {
case 1:
monthName = 'January';
break;
case 2:
monthName = 'February';
break;
case 3:
monthName = 'March';
break;
case 4:
monthName = 'April';
break;
case 5:
monthName = 'May';
break;
case 6:
monthName = 'June';
break;
case 7:
monthName = 'July';
break;
case 8:
monthName = 'August';
break;
case 9:
monthName = 'September';
break;
case 10:
monthName = 'October';
break;
case 11:
monthName = 'November';
break;
case 12:
monthName = 'December';
break;
default:
monthName = 'Invalid month';
}
console.log(monthName); // November
올바른 예제는 다음과 같다
- default 에는 break 를 생략하는것 노말하다
default 문이 실행되면 switch 문도 끝나기 때문이다
하지만 break 가 없는 폴스루 현상이 나타나는 switch 문을 사용하는 경우도 있다
var year = 2000; // 2000년은 윤년으로 2월이 29일이다.
var month = 2;
var days = 0;
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
days = 31;
break;
case 4: case 6: case 9: case 11:
days = 30;
break;
case 2:
// 윤년 계산 알고리즘
// 1. 년도가 4로 나누어 떨어지는 해는 윤년(2000, 2004, 2008, 2012, 2016, 2020…)
// 2. 그 중에서 년도가 100으로 나누어 떨어지는 해는 평년(2000, 2100, 2200...)
// 3. 그 중에서 년도가 400으로 나누어 떨어지는 해는 윤년(2000, 2400, 2800...)
days = ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0)) ? 29 : 28;
break;
default:
console.log('Invalid month');
}
console.log(days); // 29
switch 문은 case, default, break 등 다양한 키워드를 사용해야 하고 폴스루가 발생하는 등 문법도 복잡하다. if…else 문으로 해결할 수 있다면 if…else 문을 사용하는 편이 좋다.
하지만 if…else 문보다 switch 문을 사용했을 때 가독성이 더 좋다면 switch 문을 사용하는 편이 좋다.
참고로 파이썬은 switch 문이 없다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
반복문
반복문은 조건식의 평가 결과가 참인 경우 코드블록을 실행하고
그 후 조건식을 다시 또 평가해서
여전히 참이면 또 실행한다
조건식이 거짓이되면 동작을 종료한다
JS 에서는 3가지 반복문
for , while, do...while 을 제공중
그 외에도 for..in 문, ES6에서 새롭게 도입된 for…of 문이 있다. for..in 문과 for…of 문에 대해서는 나중에 살펴보기로 하자.
for 문
조건식이 거짓이 될때 까지 코드블록을 반복실행
for (초기화식; 조건식; 증감식) {
조건식이 참인 경우 반복 실행될 문;
}
JS deepdive 에서 for 문은 굉장히 중요하다고 말하고있음
for (var i = 0; i < 2; i++) {
console.log(i);
}
위 예제의 for 문은 변수 i가 0으로 초기화된 상태에서 시작하여 i가 2보다 작을 때까지 코드 블록을 2번 반복 실행한다. for 문의 실행 순서를 따라가며 어떻게 동작하는지 살펴보자.
- for 문을 실행하면 가장 먼저 초기화식
var i = 0
이 실행된다. 초기화식은 단 한번만 실행된다. - 초기화식의 실행이 종료되면 조건식으로 실행 순서가 이동한다. 현재 변수 i는 0이므로 조건식의 평가 결과는 true다.
- 조건식의 평가 결과가 true이므로 실행 순서가 코드 블록으로 이동하여 실행된다. 증감문으로 실행 순서가 이동하는 것이 아니라 코드 블록으로 실행 순서가 이동하는 것에 주의하자.
- 코드 블록의 실행이 종료하면 증감식으로 실행 순서가 이동한다. 증감식 i++가 실행되어 i는 1이 된다.
- 증감식 실행이 종료되면 다시 조건식으로 실행 순서가 이동한다. 초기화식으로 실행 순서가 이동하는 것이 아니라 조건식으로 실행 순서가 이동하는 것에 주의하자. 초기화식은 단 한번만 실행된다. 현재 변수 i는 1이므로 조건식의 평가 결과는 true다.
- 조건식의 평가 결과가 true이므로 실행 순서가 코드 블록으로 이동하여 실행된다.
- 코드 블록의 실행이 종료하면 증감식으로 실행 순서가 이동한다. 증감식 i++가 실행되어 i는 2가 된다.
- 증감식 실행이 종료되면 다시 조건식으로 실행 순서가 이동한다. 현재 변수 i는 2이므로 조건식의 평가 결과는 false다. 조건식의 평가 결과가 false이므로 for 문의 실행이 종료된다.
아래 예제는 위 예제를 역으로 반복하는 for 문이다. 변수 i가 1으로 초기화된 상태에서 시작하여 i가 0보다 같거나 커질 때까지 코드 블록을 2번 반복 실행한다.
- 여기서 잠깐 솔직하게 for 문은 실제로 글로 봐서는 이해가 어렵다고 생각합니다
실제로 본인이 스스로 사용을하면서 시간복잡도나 알고리즘 문제를 풀면서 익히는게 제일중요하다고
생각합니다 - 실제로 반복문은 굉장히 많이쓰이고 있지만 글로써 이해하기는 아직어려움이 있다고 생각합니다
제 자신 포함
// 무한루프
for (;;) { }
- for 문의 초기화식, 조건식, 증감식은 모두 옵션
어떤 식도 선언하지 않으면 무한 루프가 됨
for (var i = 1; i <= 6; i++) {
for (var j = 1; j <= 6; j++) {
if (i + j === 6) console.log(`[${i}, ${j}]`);
}
}
[1, 5]
[2, 4]
[3, 3]
[4, 2]
[5, 1]
- for 문 내에 for 문을 중첩해 사용할 수 있다.
아래는 두 개의 주사위를 던졌을 때, 두 눈의 합이 6이 되는 모든 경우의 수를 출력하는 예제다. - 위와 같은 이중반복문은 정말로 생각을 잘해보고 사용해야하는 경우가있음
배열과 객체를 사용하는 경우
시간복잡도가 정말로 크게 달라질수있음
While 문
- while 문은 조건식의 결과가 참이면 코드 블록을 계속해서 반복 실행
조건문의 결과가 거짓이 되면 실행을 종료한다
만약 조건식의 결과가 불리언 값이 아니면 불리언 값으로 강제 변환되어 논리적 참, 거짓을 구별
var count = 0;
// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
while (count < 3) {
console.log(count);
count++;
} // 0 1 2
조건식의 결과가 언제나 참 이 면 무한루프 발생
var count = 0;
// 무한루프
while (true) {
console.log(count);
count++;
// count가 3이면 코드 블록을 탈출한다.
if (count === 3) break;
} // 0 1 2
무한루프에서 탈출하기 위해선 코드블록내에 if문으로 탈출 조건을 만들고 break문으로 코드 블록을 탈출
do...While 문
do…while 문은 코드 블록을 실행하고 조건식을 평가
따라서 코드 블록은 무조건 한번 이상 실행된다
무조건 한번이상 실행된다는거를 유의하면 좋을것같습니다
var count = 0;
// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
do {
console.log(count);
count++;
} while (count < 3); // 0 1 2
break ( switch , 반복문 멈춰!!!!!!!!!!)
- switch 문과 while 문에서 살펴보았듯이 break 문은 코드 블록을 탈출한다
좀 더 정확히 표현하자면 코드 블록을 탈출하는 것이 아니라 레이블 문, 반복문(for, for…in, for…of, while, do…while) 또는 switch 문의 코드 블록을 탈출한다.
레이블 문, 반복문, switch 문의 코드 블록 이외에 break 문을 사용하면 SyntaxError(문법 에러)가 발생한다 - 필수요소라는 생각이 듭니다 실제로 무한루프가 반복되면 메모리 사용량이 증가하면서
실제로 문제가 생기는경우가 굉장히많고
switch 문을 사용하는경우엔 default 값이 출력될수있으니
항상 신경을 써주기로 합시다
**) 레이블 문이란 식별자가 붙은 문
// foo라는 레이블 식별자가 붙은 레이블 문
foo: console.log('foo');
레이블 문은 프로그램의 실행 순서를 제어하기 위해 사용한다.
사실 switch 문의 case 문과 default 문도 레이블 문이다
레이블 문을 탈출하려면 break 문에 레이블 식별자를 지정한다
// foo라는 식별자가 붙은 레이블 블록문
foo: {
console.log(1);
break foo; // foo 레이블 블록문을 탈출한다.
console.log(2);
}
console.log('Done!');
- for 문 안에 for 문을 사용하는경우
내부 for 문에서 break문을 실행하면 내부 for 문을 탈출하여 외부for 문으로 진입을하는데
이때 내부 for 문이 아닌 외부 for 문을 탈출하려면 레이블 문을 사용한다
// outer라는 식별자가 붙은 레이블 for 문
outer: for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
// i + j === 3이면 외부 for 문을 탈출한다.
if (i + j === 3) break outer;
}
}
console.log('Done!');
실제로 아직 레이블문을 사용해본적이없습니다...프론트에서는 많이 쓰시는지
개인적으로 궁금하기도합니다
이중 반복문을 거의 사용하지 않아서 그런것같습니다
중첩된 for 문을 외부로 탈출할 때 레이블 문은 유용하지만 그 외의 경우 레이블 문은 일반적으로 권장하지 않는다. 레이블 문을 사용하면 프로그램의 흐름이 복잡해져서 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문이다.
라고 설명이 나와 있군요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
- break 문은 레이블 문 뿐만이 아니라 반복문, switch 문에서도 사용 가능
이 경우에는 break 문에 레이블 식별자를 지정하지 않음
break 문은 반복문을 더 이상 진행하지 않아도 될 때 불필요한 반복을 하지않는다 - 아래는 문자열에서 특정 문자의 인덱스(위치)를 검색하는 예제
var string = 'Hello World.';
var index;
// 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 문자열의 개별 문자가 'l'이면
if (string[i] === 'l') {
index = i;
break; // 반복문을 탈출한다.
}
}
console.log(index); // 2
// 참고로 String.prototype.indexOf 메소드를 사용해도 같은 동작을 한다.
console.log(string.indexOf('l')); // 2
이렇게 유용한 함수들이 이미 JS 내에 존재하고있습니다
굉장한 효과를 누릴수있고 내장함수보다빠른 함수는 거의없다 라고 생각합니다 ㅋㅋ
continue 문
- continue문은 반복문의 코드블록 실행을 현지점에서 중단하고
반복문의 증감식으로 실행 흐름을 이동시킵니다
break문처럼 탈출은 안함 추노 ㄴ
다음 예제는 특정문자의 개수를 세는 예
var string = 'Hello World.';
var count = 0;
// 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
if (string[i] !== 'l') continue;
count++; // continue 문이 실행되면 이 문은 실행되지 않는다.
}
console.log(count); // 3
// 참고로 String.prototype.match 메소드를 사용해도 같은 동작을 한다.
console.log(string.match(/l/g).length); // 3
(원래 처음엔 레거시를 배워야합니다 동작원리를 이해하는것이 중요하다고 생각합니다)
하지만 실제업무에선 내장함수를 사용합시다 ㅎㅎ
- 실행해야 할 코드가 한 줄이라면 continue 문을 사용했을 때보다 간편하며 가독성도 좋다.
하지만 if 문 내에서 실행해야 할 코드가 길다면 들여쓰기가 한 단계 더 깊어지므로
continue 문을 사용하는 것이 가독성이 더 좋다.
// continue 문을 사용하지 않으면 if 문 내에 코드를 작성해야 한다.
for (var i = 0; i < string.length; i++) {
// 'l'이면 카운트를 증가시킨다.
if (string[i] === 'l') {
count++;
// code
// code
// code
}
}
// continue 문을 사용면 if 문 밖에 코드를 작성할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 카운트를 증가시키지 않는다.
if (string[i] !== 'l') continue;
count++;
// code
// code
// code
}
진짜 조건문
- 말그대로 특정 조건이 참이면 그해당 구문의 코드를 실행시킨다라고 축약시킬수있습니다
- 논리적으로 참이거나 거짓일 경우에 따라 실행할 코드를 적는다 라고 생각할수있습니다
- if....else 문과 switch 문 두가지의 조건문을 제공하고있습니다
if...else
if (조건식) {
// if 조건식이 참이면 해당 코드블록이 실행
} else {
// else 조건식이 참이면 해당코드블록이 실행
}
if 문의 조건식은 불리언값으로 값이 나와야만합니다
만약 if 문의 조건식이 불리언 값이 아닌 값으로 나온다면
JS엔진에 의해 암묵적으로 강제적으로 불리언 값으로 변환되어
실행할 코드 블록을 결정합니다조건식을 추가하여 여러 조건에 따라 실행될 코드 블록을 늘리고 싶다면 else if 문을 사용가능
if (조건식) {
// if 조건식이 참이면 해당 코드블록이 실행
} else if (조건식2) {
// else 조건식2가 참이면 해당코드블록이 실행
} else {
// 조건식 1,2 가 모두 거짓이면 해당 코드블록이 실행
}
- else if 문과 else 문은 모두다 옵션입니다
실제로 사용해도 되고 안해도 됩니다
if 와 else 는 2번이상 사용할수없지만
else if 는 여러번 사용 가능합니다
let num = 2;
let kind
// if 문
if (num > 0) {
kind = '양수'; // 음수를 구별 불가
}
console.log(kind)
// if ..else
if (num > 0 ) {
kind = '양수';
} else {
kind = '음수'
}
console.log(kind)
// if ...else if
if(num > 0) {
kind = '양수';
} else if (num < 0) {
kind = '음수';
} else {
kind = '0'
}
console.log(kind)
만약 코드블록내의 구문이 하나라면 중괄호 생략가능
if (true) console.log(123)
// 이것또한 동작합니다
하지만 else if 문까지 있는경우에 조건문이 점점 복잡해진다면 중괄호로 구문의 끝을 나타내지않는다면
유지보수과정에서 인간적인 오류가 생길수도있다고 생각합니다
단순한 조건문에서는 사용해도 되지만
점점 많아지는 조건문에서는 중괄호를 사용하는게 맞다고 생각합니다
삼항연산자를 사용해서도 표현이 가능하다
// if ..else
if (num > 0 ) {
kind = '양수';
} else {
kind = '음수'
}
console.log(kind)
와 같은 예제를
let result = num > 0 ? '양수' : '음수'
// if ...else if
if(num > 0) {
kind = '양수';
} else if (num < 0) {
kind = '음수';
} else {
kind = '0'
}
console.log(kind)
와 같은예제도
let result = num ? ( num > 0 ? '양수' : '음수') : '0'
하지만 밑에 삼항연사자 예제는 사실상
삼항연산자 안에 삼항연산자가 잇다고 생각할수잇음
2개의 삼항연산자가 존재하는경우
개인적인 생각으로나 리뷰 를 받다보면 if..else 에서만 삼항연산자를 사용하는게
깔끔하다고 생각합니다
switch 문
- switch 는 주어진 표현식을 평가하여
그값과 일치하는 값을 갖는 case 문으로 실행 순서를 바꾼다
case 문은 상황의 의미하는 표현식을 지정하고 콜론으로 마침표를 찍어준다
그리고 그뒤에 실행할 코드구문을 위치 시킨다 - switch 문의 표현식과 일치하는 case 문이 없다면
실행순서는 default 문으로 이동
default 문은 선택사항으로 사용하기도 하고 안하기도 한다
switch(표현식) {
case 표현식1;
switch 의 표현식과 표현식1이 일치하면 실행될 구문
break;
case 표현식2;
switch 의 표현식과 표현식2와 일치하면 실행될 구문
break;
default:
switch 의 표현식과 일치하는 case 문이 없을 때 실행될 구문
}
- if...else 문의 조건식은 참과 거짓 불리언 값으로 평가되어야하지만
switch 문 표현식은 불리언 값보다는
문자열이나 숫자인 경우가 많다 - 고로 생각해본다면 if...else 는 논리적으로 참, 거짓으로 실행할 코드를 결정하고
switch 는 논리적인 참,거짓 보다는 좀더 다양한상황에 따라 실행할 코드를 결정한다
// 월을 영어로 변환한다. (11 → 'November')
var month = 11;
var monthName;
switch (month) {
case 1:
monthName = 'January';
case 2:
monthName = 'February';
case 3:
monthName = 'March';
case 4:
monthName = 'April';
case 5:
monthName = 'May';
case 6:
monthName = 'June';
case 7:
monthName = 'July';
case 8:
monthName = 'August';
case 9:
monthName = 'September';
case 10:
monthName = 'October';
case 11:
monthName = 'November';
case 12:
monthName = 'December';
default:
monthName = 'Invalid month';
}
console.log(monthName); // Invalid month
여기서 잠깐쓰으으으으으
실제로 해당예제를 실행시켜보면 Invalid month 가 실행된다
왜냐하면 case문에 따라 코드구문 순서가 변경은되었지만
코드구문을 실행하고나서 탈출하지못하고
계속 반복해서 switch 문이 끝날때까지 저 예제 안에서 머물었기 때문이다
이와 같은 경우를 폴스루 라고한다
실제로 november 가 할당되었지만
끝나지않고 다음 case인 december 가 재할당되었고
그러고 나서도 탈출을 못해서
마지막 default case 까지 나와서 종료가 된상황
- 이러한 폴스루 현상을 방지하기위해서는
case 코드구문 마지막에 break 를 사용해주어야만한다 - break는 코드블록에서 탈출하는 역할을해준다
// 월을 영어로 변환한다. (11 → 'November')
var month = 11;
var monthName;
switch (month) {
case 1:
monthName = 'January';
break;
case 2:
monthName = 'February';
break;
case 3:
monthName = 'March';
break;
case 4:
monthName = 'April';
break;
case 5:
monthName = 'May';
break;
case 6:
monthName = 'June';
break;
case 7:
monthName = 'July';
break;
case 8:
monthName = 'August';
break;
case 9:
monthName = 'September';
break;
case 10:
monthName = 'October';
break;
case 11:
monthName = 'November';
break;
case 12:
monthName = 'December';
break;
default:
monthName = 'Invalid month';
}
console.log(monthName); // November
올바른 예제는 다음과 같다
- default 에는 break 를 생략하는것 노말하다
default 문이 실행되면 switch 문도 끝나기 때문이다
하지만 break 가 없는 폴스루 현상이 나타나는 switch 문을 사용하는 경우도 있다
var year = 2000; // 2000년은 윤년으로 2월이 29일이다.
var month = 2;
var days = 0;
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
days = 31;
break;
case 4: case 6: case 9: case 11:
days = 30;
break;
case 2:
// 윤년 계산 알고리즘
// 1. 년도가 4로 나누어 떨어지는 해는 윤년(2000, 2004, 2008, 2012, 2016, 2020…)
// 2. 그 중에서 년도가 100으로 나누어 떨어지는 해는 평년(2000, 2100, 2200...)
// 3. 그 중에서 년도가 400으로 나누어 떨어지는 해는 윤년(2000, 2400, 2800...)
days = ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0)) ? 29 : 28;
break;
default:
console.log('Invalid month');
}
console.log(days); // 29
switch 문은 case, default, break 등 다양한 키워드를 사용해야 하고 폴스루가 발생하는 등 문법도 복잡하다. if…else 문으로 해결할 수 있다면 if…else 문을 사용하는 편이 좋다.
하지만 if…else 문보다 switch 문을 사용했을 때 가독성이 더 좋다면 switch 문을 사용하는 편이 좋다.
참고로 파이썬은 switch 문이 없다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
반복문
반복문은 조건식의 평가 결과가 참인 경우 코드블록을 실행하고
그 후 조건식을 다시 또 평가해서
여전히 참이면 또 실행한다
조건식이 거짓이되면 동작을 종료한다
JS 에서는 3가지 반복문
for , while, do...while 을 제공중
그 외에도 for..in 문, ES6에서 새롭게 도입된 for…of 문이 있다. for..in 문과 for…of 문에 대해서는 나중에 살펴보기로 하자.
for 문
조건식이 거짓이 될때 까지 코드블록을 반복실행
for (초기화식; 조건식; 증감식) {
조건식이 참인 경우 반복 실행될 문;
}
JS deepdive 에서 for 문은 굉장히 중요하다고 말하고있음
for (var i = 0; i < 2; i++) {
console.log(i);
}
위 예제의 for 문은 변수 i가 0으로 초기화된 상태에서 시작하여 i가 2보다 작을 때까지 코드 블록을 2번 반복 실행한다. for 문의 실행 순서를 따라가며 어떻게 동작하는지 살펴보자.
- for 문을 실행하면 가장 먼저 초기화식
var i = 0
이 실행된다. 초기화식은 단 한번만 실행된다. - 초기화식의 실행이 종료되면 조건식으로 실행 순서가 이동한다. 현재 변수 i는 0이므로 조건식의 평가 결과는 true다.
- 조건식의 평가 결과가 true이므로 실행 순서가 코드 블록으로 이동하여 실행된다. 증감문으로 실행 순서가 이동하는 것이 아니라 코드 블록으로 실행 순서가 이동하는 것에 주의하자.
- 코드 블록의 실행이 종료하면 증감식으로 실행 순서가 이동한다. 증감식 i++가 실행되어 i는 1이 된다.
- 증감식 실행이 종료되면 다시 조건식으로 실행 순서가 이동한다. 초기화식으로 실행 순서가 이동하는 것이 아니라 조건식으로 실행 순서가 이동하는 것에 주의하자. 초기화식은 단 한번만 실행된다. 현재 변수 i는 1이므로 조건식의 평가 결과는 true다.
- 조건식의 평가 결과가 true이므로 실행 순서가 코드 블록으로 이동하여 실행된다.
- 코드 블록의 실행이 종료하면 증감식으로 실행 순서가 이동한다. 증감식 i++가 실행되어 i는 2가 된다.
- 증감식 실행이 종료되면 다시 조건식으로 실행 순서가 이동한다. 현재 변수 i는 2이므로 조건식의 평가 결과는 false다. 조건식의 평가 결과가 false이므로 for 문의 실행이 종료된다.
아래 예제는 위 예제를 역으로 반복하는 for 문이다. 변수 i가 1으로 초기화된 상태에서 시작하여 i가 0보다 같거나 커질 때까지 코드 블록을 2번 반복 실행한다.
- 여기서 잠깐 솔직하게 for 문은 실제로 글로 봐서는 이해가 어렵다고 생각합니다
실제로 본인이 스스로 사용을하면서 시간복잡도나 알고리즘 문제를 풀면서 익히는게 제일중요하다고
생각합니다 - 실제로 반복문은 굉장히 많이쓰이고 있지만 글로써 이해하기는 아직어려움이 있다고 생각합니다
제 자신 포함
// 무한루프
for (;;) { }
for 문의 초기화식, 조건식, 증감식은 모두 옵션
어떤 식도 선언하지 않으면 무한 루프가 됨for (var i = 1; i <= 6; i++) { for (var j = 1; j <= 6; j++) { if (i + j === 6) console.log(`[${i}, ${j}]`); } }
[1, 5]
[2, 4]
[3, 3]
[4, 2]
[5, 1]
- for 문 내에 for 문을 중첩해 사용할 수 있다.
아래는 두 개의 주사위를 던졌을 때, 두 눈의 합이 6이 되는 모든 경우의 수를 출력하는 예제다.
- 위와 같은 이중반복문은 정말로 생각을 잘해보고 사용해야하는 경우가있음
배열과 객체를 사용하는 경우
시간복잡도가 정말로 크게 달라질수있음
### While 문
- while 문은 조건식의 결과가 참이면 코드 블록을 계속해서 반복 실행
조건문의 결과가 거짓이 되면 실행을 종료한다
만약 조건식의 결과가 불리언 값이 아니면 불리언 값으로 [강제 변환](https://poiemaweb.com/js-type-coercion)되어 논리적 참, 거짓을 구별
```jsx
var count = 0;
// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
while (count < 3) {
console.log(count);
count++;
} // 0 1 2
조건식의 결과가 언제나 참 이 면 무한루프 발생
var count = 0;
// 무한루프
while (true) {
console.log(count);
count++;
// count가 3이면 코드 블록을 탈출한다.
if (count === 3) break;
} // 0 1 2
무한루프에서 탈출하기 위해선 코드블록내에 if문으로 탈출 조건을 만들고 break문으로 코드 블록을 탈출
do...While 문
do…while 문은 코드 블록을 실행하고 조건식을 평가
따라서 코드 블록은 무조건 한번 이상 실행된다
무조건 한번이상 실행된다는거를 유의하면 좋을것같습니다
var count = 0;
// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
do {
console.log(count);
count++;
} while (count < 3); // 0 1 2
break ( switch , 반복문 멈춰!!!!!!!!!!)
- switch 문과 while 문에서 살펴보았듯이 break 문은 코드 블록을 탈출한다
좀 더 정확히 표현하자면 코드 블록을 탈출하는 것이 아니라 레이블 문, 반복문(for, for…in, for…of, while, do…while) 또는 switch 문의 코드 블록을 탈출한다.
레이블 문, 반복문, switch 문의 코드 블록 이외에 break 문을 사용하면 SyntaxError(문법 에러)가 발생한다 - 필수요소라는 생각이 듭니다 실제로 무한루프가 반복되면 메모리 사용량이 증가하면서
실제로 문제가 생기는경우가 굉장히많고
switch 문을 사용하는경우엔 default 값이 출력될수있으니
항상 신경을 써주기로 합시다
**) 레이블 문이란 식별자가 붙은 문
// foo라는 레이블 식별자가 붙은 레이블 문
foo: console.log('foo');
레이블 문은 프로그램의 실행 순서를 제어하기 위해 사용한다.
사실 switch 문의 case 문과 default 문도 레이블 문이다
레이블 문을 탈출하려면 break 문에 레이블 식별자를 지정한다
// foo라는 식별자가 붙은 레이블 블록문
foo: {
console.log(1);
break foo; // foo 레이블 블록문을 탈출한다.
console.log(2);
}
console.log('Done!');
- for 문 안에 for 문을 사용하는경우
내부 for 문에서 break문을 실행하면 내부 for 문을 탈출하여 외부for 문으로 진입을하는데
이때 내부 for 문이 아닌 외부 for 문을 탈출하려면 레이블 문을 사용한다
// outer라는 식별자가 붙은 레이블 for 문
outer: for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
// i + j === 3이면 외부 for 문을 탈출한다.
if (i + j === 3) break outer;
}
}
console.log('Done!');
실제로 아직 레이블문을 사용해본적이없습니다...프론트에서는 많이 쓰시는지
개인적으로 궁금하기도합니다
이중 반복문을 거의 사용하지 않아서 그런것같습니다
중첩된 for 문을 외부로 탈출할 때 레이블 문은 유용하지만 그 외의 경우 레이블 문은 일반적으로 권장하지 않는다. 레이블 문을 사용하면 프로그램의 흐름이 복잡해져서 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문이다.
라고 설명이 나와 있군요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
- break 문은 레이블 문 뿐만이 아니라 반복문, switch 문에서도 사용 가능
이 경우에는 break 문에 레이블 식별자를 지정하지 않음
break 문은 반복문을 더 이상 진행하지 않아도 될 때 불필요한 반복을 하지않는다 - 아래는 문자열에서 특정 문자의 인덱스(위치)를 검색하는 예제
var string = 'Hello World.';
var index;
// 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 문자열의 개별 문자가 'l'이면
if (string[i] === 'l') {
index = i;
break; // 반복문을 탈출한다.
}
}
console.log(index); // 2
// 참고로 String.prototype.indexOf 메소드를 사용해도 같은 동작을 한다.
console.log(string.indexOf('l')); // 2
이렇게 유용한 함수들이 이미 JS 내에 존재하고있습니다
굉장한 효과를 누릴수있고 내장함수보다빠른 함수는 거의없다 라고 생각합니다 ㅋㅋ
continue 문
- continue문은 반복문의 코드블록 실행을 현지점에서 중단하고
반복문의 증감식으로 실행 흐름을 이동시킵니다
break문처럼 탈출은 안함 추노 ㄴ
다음 예제는 특정문자의 개수를 세는 예
var string = 'Hello World.';
var count = 0;
// 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
if (string[i] !== 'l') continue;
count++; // continue 문이 실행되면 이 문은 실행되지 않는다.
}
console.log(count); // 3
// 참고로 String.prototype.match 메소드를 사용해도 같은 동작을 한다.
console.log(string.match(/l/g).length); // 3
(원래 처음엔 레거시를 배워야합니다 동작원리를 이해하는것이 중요하다고 생각합니다)
하지만 실제업무에선 내장함수를 사용합시다 ㅎㅎ
- 실행해야 할 코드가 한 줄이라면 continue 문을 사용했을 때보다 간편하며 가독성도 좋다.
하지만 if 문 내에서 실행해야 할 코드가 길다면 들여쓰기가 한 단계 더 깊어지므로
continue 문을 사용하는 것이 가독성이 더 좋다.
// continue 문을 사용하지 않으면 if 문 내에 코드를 작성해야 한다.
for (var i = 0; i < string.length; i++) {
// 'l'이면 카운트를 증가시킨다.
if (string[i] === 'l') {
count++;
// code
// code
// code
}
}
// continue 문을 사용면 if 문 밖에 코드를 작성할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 카운트를 증가시키지 않는다.
if (string[i] !== 'l') continue;
count++;
// code
// code
// code
}
마무리 총평 실제로 반복문과 조건문은 실제로 쓰는 경우가 정말로 많다고 생각합니다
실제로 조건문을 구성할때도 error 에 대해서 어떻게 대응할것인지 고민을 하는경우도 굉장히 많습니다
백엔드 개발자 기준인지는 모르겠지만요 ㅎㅎ
return 값으로 error 를 지정해놓고
실제로 조건에 맞으면 정상동작을 하게 만들수도있고
이와 반대의 경우로 코드를 짤수있다고 생각합니다
위와 같은 코드 작성 철학은 개개인마다 다르다고 생각하기때문에
저는 실제로 경험을 해보면서 작성을해야한다고 생각합니다
안나야하는 에러가 나는것이
나야하는에러가 안나는것보단 100000배는 더 좋습니다
삼항연산자를 사용할수잇는 경우에서도
실제로 안쓰고 if else 로 나타내는경우가잇듯이
본인의 코딩 철학을 녹여내길 바랍니다
반복문과 조건문은 예제가 너무 많아서 조금 힘들엇지만
그래도 저도 다시 한번 공부가 되는 시간이엿습니다
긴글 읽어주셔서 감사합니다
출처 : 모던자바스크립트 Deep dive
'Programming(ko,en) > Javascript' 카테고리의 다른 글
How does a browser works? (0) | 2022.10.12 |
---|---|
What is the JavaScript? (1) | 2022.10.10 |
Java Script Basic concepts (기본개념) (0) | 2022.10.07 |
JS 실행컨텍스트?...그게 뭔데요?... (0) | 2022.02.05 |
JS 스코프에 대해서...알고싶지않지만 알아야겟지 (0) | 2022.01.23 |