숑숑이의 개발일기

if와 삼항연산자를 사용한 조건 처리

조건에 따라 다른 행동을 취해야 할 때에는, if문을 사용하거나 조건부 연산자 ?를 사용한다.

 

if문

괄호안의 조건을 평가하여 해당 결과가 true라면 코드를 실행한다.

let year = prompt('저는 몇년생일까요?', '');
if (year == 2001)
	alert('정답입니다.');
    
// 복수의 문을 실행하고 싶다면 중괄호로 코드블록을 감싼다
if (year == 2001) {
	alert('정답');
    alert('입니다!');
}

코드의 가독성을 위해서는, 실행 구문이 한 줄 이더라도 중괄호를 사용해 감싸는 것을 추천한다.

 

if문은 괄호 안의 표현식을 평가하고, 그 결과를 불린값으로 변환한다.

=> 0, 빈문자열, null, nudefined, NaN과 falsy한 값도 표현식에 사용이 가능한 것.

 

else절과 else if

if문에는 else절을 붙일 수 있는데, else 절에는 조건이 거짓일 때 실행된다. 유사하지만 약간씩 차이가 있는 조건 여러개를 처리할 경우, else if문을 사용할 수도 있다.

let age = propmt('제 나이는 몇살일까요?', '');

if (age < 23) {
	alert('숫자를 좀 더 올려보세요.');
} else if (age > 23) {
	alert('숫자를 좀 더 내려보세요.');
} else {	// 선택사항
	alert('정답입니다.');
}

 

조건부 연산자 ?

조건부 연산자는 물음표로 표시하며 피연산자가 세 개이므로 삼항연산자라고도 부른다. 

let result = condition ? val1 : val2;
// 조건에 따라 다른 값 할당

 

물음표 연산자를 여러개 연결하여 복수의 조건을 처리할 수도 있다.

let age = prompt('나이를 입력해주세요.', 18);

let message = (age < 3) ? '아기야 안녕?' :
  (age < 18) ? '안녕!' :
  (age < 100) ? '환영합니다!' :
  '나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!';

alert( message );

이러한 코드는 아래의 if..else로 변환할 수도 있다.

if (age < 3) {
  message = '아기야 안녕?';
} else if (age < 18) {
  message = '안녕!';
} else if (age < 100) {
  message = '환영합니다!';
} else {
  message = '나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!';
}

 

 

논리 연산자

자바스크립트에는 세 종류의 논리연산자 ||, &&, !가 존재한다. 논리연산자는 피연산자로 불린형 뿐만아니라 모든 타입의 값을 받을 수 있다.

 

 

||(OR)

OR연산자는 인수 중 하나라도 true면 true를 반환하고, 그렇지 않으면 false르 반환한다. OR연산자에서 피연산자가 여러개인 경우 가장 왼쪽 피연산자부터 시작해 오른쪽 방향으로 연산을 수행한다. 각 피연산자를 불린형으로 반환하여 그 값이 true인 경우 연산을 멈추고 해당 피연산자의 변환 전 원래의 값을 반환한다. 또한, 피연산자에 truthy가 하나도 없다면 마지막 피연산자를 반환한다.

이러한 기능을 이용하여 여러 용도에서 OR 연산자를 활용할 수 있다. 예를들어 변수 또는 표현식으로 구성된 목록에서 첫 번째 truthy를 찾는다는 지 말이다.

 

만약 OR 연산자의 피연산자가 alert인 경우?

alert( alert(1) || 2 || alert(3));	// 2

 

alert으로 1, 2가 실행된다. 그러나 alert 함수는 undefined를 반환하므로 OR 연산자는 다음 2를 평가한다.

 

 

&&(AND)

AND 연산자는 두 피연산자가 모두 참일때 true를 반환한다. 이외의 경우에는 false를 반환한다. OR연산자와 마찬가지로 피연산자의 타입에 제약이 없다.

AND 연산자의 경우 첫번째 falsy를 찾는다. 연산순서는 OR과 같다. 또한 똑같이 false인 경우 해당 피연산자의 변환 전 원래의 값을 반환한다. 

 

 

!(NOT)

NOT은 느낌표를 써서 만들 수 있다. 인수를 하나만 받고, 피 연산자를 불린형으로 반환하여 변환된 값의 역을 반환하는 순으로 연산을 수행한다.

alert(!true);	// false
alert(!0);	// true

// 두개 연달아 사용하여 값을 불린형으로 반환할 수 있다.
alert(!!"empty");	// true
alert(!!null);	// false

// 위의 내용을 내장함수 Boolean()을 사용해서도 같은 결과를 얻어낼 수 있다.
alert(Boolean("empty"));	// true

NOT 연산자는 모든 논리연산자 중 우선순위가 가장 높다. 고로 항상 &&와 ||보다 먼저 실행된다.

 

ON AND OR 연산자로 구성된 표현식 예시

alert(null || 2 && 3 || 4);
// 먼저 2 && 3이 실행되어 alert(null || 3 || 4)으로 변환되고
// 고로 첫번째 truthy인 3이 alert으로 출력된다.

 

로그인 구현하기

let userName = prompt("사용자 이름을 입력해주세요.", '');

if (userName == 'Admin') {

  let pass = prompt('비밀번호:', '');

  if (pass == 'TheMaster') {
    alert( '환영합니다!' );
  } else if (pass == '' || pass == null) {
    alert( '취소되었습니다.' );
  } else {
    alert( '인증에 실패하였습니다.' );
  }

} else if (userName == '' || userName == null) {
  alert( '취소되었습니다.' );
} else {
  alert( "인증되지 않은 사용자입니다." );
}

 

 

nullish 병합 연산자. ??

??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 확정되어 있는 변수를 찾을 수 있다.

 

a ?? b의 평가 결과는 아래의 설명과 같다.

  • a가 null, undefined가 아니면 a
  • 이외의 경우 b

이러한 절차를 비교연산자와 논리연산자만으로 작성하면 아래와 같다.

x = (a !== null && a !== undefined) ? a : b;

 

 

||는 첫 번째 truthy를 반환, ??는 첫번째 정의된(defined) 값을 반환한다는 것을 잊지말자.

 

??의 연산자 우선순위는 5로 꽤 낮다. 고로 복잡한 표현식 안에서 ??를 사용할 경우 괄호를 추가해 사용하자. 또한 안정성 관련 이슈로 ??는 &&와 ||와 함께 사용하지 못한다. 이 제약을 피하기 위해서는 아래와 같이 괄호를 추가하여 사용하자.

let x = (1 && 2) ?? 3;

 

 

While과 for 반복문

반복문(loop)를 사용하여 동일한 코드를 여러번 반복할 수 있다.

 

while 반복문

while (condition) {
	// 반복문 본문
}

condition(조건)이 true면 반복문 본문의 코드가 실행된다. 

반복문 본문이 한 번 실행되는 것을 반복(iteration, 이터레이션)이라고 한다.

 

 

do..while 반복문

do..while 반복문을 활용해 조건문을 본문 아래로 옮길 수 있다. 이때에는 while 반복문과 다르게 본문을 무조건 한 번이상 실행한다. 다르게 말해, 본문을 최소한 한 번이라도 실행하고 싶을때에 사용한다. 대다수의 사황에서는 do..while 보다는 while을 사용하는편이다.

do {
	// 본문
} while (condition);

 

 

for 반복문

for은 가장 많이 쓰이는 반복문이다. 

for (begin; condition; step) {
	// 본문
}

for (let i = 0; i < 3; i++) {
	alert(i);	// 0, 1, 2
}
  • begin : 반복문에 진입할 때 단 한번 실행된다.
  • condition : 반복마다 해당 조건을 확인한다. false면 반복문을 멈춘다.
  • body : condition이 truthy일 동안 실행된다.
  • step : 각 반복문의 body가 실행된 이후에 실행된다.

또한, 반복문 내에서 선언한 변수를 인라인 변수라고 부른다. 위와 같이 선언한 변수는 반복문 안에서만 접근할 수 있다. 또는, 아래와 같이 정의되어 있는 변수를 사용할 수도 있다.

let i = 0;
for (i = 0; i < 3 ; i++) {	// 기존에 정의되어 있는 변수를 사용했다.
	alert(i);
}

이렇게 정의되어 있는 변수를 사용한다면, 반복문 밖에서도 사용할 수 있는 이점이 있다.

 

구성 요소 생략

for문에서는 구성 요소를 생략하는 것도 가능하다. 반복문 실행시 아무것도 할 필요가 없다면 begin을 생략할 수 있다. 또, step도 생략할 수있다.

 

1) begin을 생략하는 경우

let i = 0;
for (; i < 3; i++) {
	alert(i);
}

 

 

2) step을 생략하는 경우

let i = 0;
for (; i < 3;) {
	alert(i++);	// begin과 step모두생략 
}

 

 

3) 모든 구성요소를 생략하는 경우(무한 반복문)

for (;;) {
	// 무한반복
}

 

그리고 for문을 사용할 때 주의사항으로는, 두 개의 세미콜론은 꼭 넣어주어야 한다. 하나라도 누락한 경우 문법에러가 발생한다.

 

반복문 빠져나오기 - break

대개는 반복문의 조건이 falsy가 되면 반복문이 종료된다. 그런데 break라는 키워드를 사용하여 원하는 때에 반복문을 빠져나올 수있다. 

let sum = 0;

while (true) {

  let value = +prompt("숫자를 입력하세요.", '');

  if (!value) break; // (*)

  sum += value;

}
alert( '합계: ' + sum );

위의 예시서 *로 표시한 줄의 코드를 보자. prompt에 아무것도 입력하지않았거나, 0을 입력한 경우 그러니까 falsy한 값을 입력한경우, 합계 계산을 멈추고 반복문을 빠져나온다.

이와같이 반복문의 시작 지점이나 끝 지점에서 조건을 확인하는 것이 아니라 본문 중 혹은 본문 여러곳에서 조건을 확인해야 하는 경우, 무한 반복문 + break 조합을 사용하면 좋다.

 

 

다음 반복으로 넘어가기 - continue

continue는 break의 가벼운 버전이다. break는 해당 반복문을 종료하는 반면 continue는 전체 반복문을 멈추지는 않는다. 대신 현재 이터레이션을 멈추고 다음 이터레이션을 강제로 실행시킨다. (조건 성립시)

정리해, continue는 현재 반복문을 종료시키고 다음 반복으로 넘어가고 싶을 때 사용할 수 있다.

for (let i = 0; i < 10; i++) {

  // i가 짝수라면 본문은 실행되지 않는다.
  if (i % 2 == 0) continue;

  alert(i); // 1, 3, 5, 7, 9가 차례대로 출력됨
}

 

주의사항

삼항연산자 ? 오른쪽에는 break나 continue가 올 수 없다.

if (i > 5) {
	alert(i);
} else {
	continue;
}

// 위와 같은 코드를 아래처럼 바꿀 수 없다. (문법에러)
(i > 5) ? alert(i) : continue;

 

 

break/continue와 레이블

여러 개의 중첩 반복문을 한 번에 빠져나와야 하는 경우가 종종 생긴다. 이때 break 지시자를 사용하면 안쪽에 있는 반복문만 빠져나올 수 있다. 고로 중첩 반복문을 한 번에 빠져나와야 할 경우 레이블을 사용하면 된다.

 

레이블(label)은 반복문 앞에 콜론과 함께 쓰이는 식별자다.

labelName : for (...) {
	...
}

 

 

이러한 레이블을 반복문 안에서 break<labelName>문을 사용해 레이블에 해당하는 반복문을 빠져나올 수 있다.

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('완료!');

레이블을 별도의 줄에 사용하는 것도 가능하다. 

 

continue 또한 레이블과 함께 사용할 수 있다. 두 가지를 같이 사용하면 레이블이 붙은 반복문의 다음 이터레이션이 실행된다.

 

예시) 2부터 n까지의 숫자 중 소수 출력하는 코드 작성

소수를 판단하는 알고리즘은 다양한데, 중첩 반복문 및 레이블을 이용한 코드는 아래와 같이 작성할 수 있다.

let n = 10;

nextPrime:
for (let i = 2; i <= n; i++) { // 각 i에 대하여 반복문을 돌림

  for (let j = 2; j < i; j++) { // 제수(나눗수)를 찾음
    if (i % j == 0) continue nextPrime; // 소수가 아니므로 다음 i로 넘어감
  }

  alert( i ); // 소수
}

 

 

switch문

복수의 if문을 switch문으로 바꿀 수 있다. switch문을 사용한 비교법은 특정 변수를 다양한 상황에서 비교할 수 있게 해준다. 

 

switch문은 하나 이상의 case문으로 구성된다. 대개 default문도 있지만, 필수는 아니다.

switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}

case문 안에 break문이 없으면 조건에 부합하는지여부를 따지지 않고 이어지는 case문을 실행하므로 되도록 써주도록 하자. 

 

break문이 없을때 아래의 코드는 값이 일치한 케이스부터 쭉 alert을 출력한다.

let a = 2 + 2;

switch (a) {
  case 3:
    alert( '비교하려는 값보다 작습니다.' );
  case 4:
    alert( '비교하려는 값과 일치합니다.' );
  case 5:
    alert( '비교하려는 값보다 큽니다.' );
  default:
    alert( "어떤 값인지 파악이 되지 않습니다." );
}

 

참고로, switch/case문은 모든 형태의 표현식을 인수로 받을 수 있다.

let a = "1";
let b = 0;

switch (+a) {	// 형변환
  case b + 1:
    alert("표현식 +a는 1, 표현식 b+1는 1이므로 이 코드가 실행됩니다.");
    break;

  default:
    alert("이 코드는 실행되지 않습니다.");
}

 

코드가 같은 case문은 아래와 같이 묶을수도 있다. 

let a = 3;

switch (a) {
	case 1 :
    	alert('더 크게 입력하세요.');
        break;
	case 2:
    case 3:
    	alert('좋아요!');
        break;
}

 

자료형의 중요성

switch문에서는 일치 비교(===)로 조건을 확인한다. 비교하려는 값과 case문의 값의 자료형과 값이 같아야 해당 case문이 실행된다. 

let arg = prompt("값을 입력해주세요.");
switch (arg) {
  case '0':
  case '1':
    alert( '0이나 1을 입력하셨습니다.' );
    break;

  case '2':
    alert( '2를 입력하셨습니다.' );
    break;

  case 3:
    alert( '이 코드는 절대 실행되지 않습니다!' );
    break;
  default:
    alert( '알 수 없는 값을 입력하셨습니다.' );
}

위와 같은 코드에서서 prompt로 입력받은 값은 문자타입이므로 3을 입력한경우 case 3:의 문은 실행되지 않는다.

profile

숑숑이의 개발일기

@숑숑-

풀스택 개발자 준비중입니다