[코어 자바스크립트] 2.11 논리 연산자

업데이트:
8 분 소요

출처 : 모던 JavaScript 튜토리얼


  • 자바스크립트에는 세 종류의 논리 연산자 ||(OR), &&(AND), !(NOT)가 있다.
  • 논리 연산자는 피연산자로 모든 타입의 값을 받을 수 있다. 연산 결과 역시 모든 타입이 될 수 있다.

1. || (OR)

  • ‘OR’ 연산자는 두 개의 수직선 기호로 만들 수 있다.
result = a || b;
  • 전통적인 픠로그래밍에서 OR 연산자는 불린값을 조작하는 데 쓰인다. 인수 중 하나라도 true이면 true를 반환하고, 그렇지 않으면 false를 반환한다. 자바스크립트이 OR 연산자는 다루기 까다롭기는 하지만 강력한 기능을 제공한다.
  • OR 연산자는 이항 연산자이므로 아래와 같이 네 가지 조합이 가능하다.
alert( true || true );   // true
alert( false || true );  // true
alert( true || false );  // true
alert( false || false ); // false 
  • 피연산자가 모두 false인 경우를 제외하고 연산 결과는 항상 true이다.
  • 피연산자가 불린형이 아니면, 평가를 위해 불린으로 변환된다. 예를 들어 연산 과정에서 숫자 1은 true로, 숫자 0은 false로 바뀐다.
if (1 || 0) { // if( true || false ) 와 동일하게 동작
  alert( 'truthy!' );
}
  • OR 연산자 ||if문에서 자주 사용되는데, 주어진 조건 중 하나라도 인지를 테스트할 때 사용할 수 있다.
let hour = 9;

if (hour < 10 ||  hour > 18) {
	alert('영업시간이 아닙니다.');
}
  • if문 안에 여러 가지 조건을 넣을 수 있다.
let hour = 12;
let isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
	alert('영업시간이 아닙니다.'); // 주말이다.
}

2. 첫 번째 truthy를 찾는 OR 연산자 ||

  • OR || 연산자와 피연산자가 여러 개인 경우도 있다.
result = value1 || value2 || value3;
  • OR || 연산자는 다음 순서에 따라 연산을 수행한다.
    • 가장 왼쪽 피연사자로부터 시작해 오른쪽으로 나아가며 피연산자를 평가한다.
    • 각 피연산자를 불린형으로 변환한다. 변환 후 그 값이 true이면 연산을 멈추고, 해당 피연산자의 변환 전 원래 값을 반환한다.
    • 피연산자 모두를 평가한 경우(모든 피연산자가 false로 평가되는 경우)에는 마지막 피연산자를 반환한다.
  • OR || 연산자를 여러 개 체이닝(chaining) 하면 첫 번째 truthy를 반환한다. 피연산자에 truthy가 하나도 없으면 마지막 피연산자를 반환한다.
alert( 1 || 0 ); // 1 (1은 truthy임)

alert( null || 1 ); // 1 (1은 truthy임)
alert( null || 0 || 1 ); // 1 (1은 truthy임)

alert( undefined || null || 0 ); // 0 (모두 falsy이므로, 마지막 값을 반환함)

여러 용도로 OR 연산자 활용하기

  1. 변수 또는 표현식으로 구성된 목록에서 첫 번째 truthy 얻기
    • firstNamelastNamenickName이란 변수가 있는데 이 값들은 모두 옵션 값이라고 가정한다. OR ||을 사용하면 실제 값이 들어있는 변수를 찾고, 그 값을 보여줄 수 있다. 변수 모두에 값이 없는 경우엔 익명를 보여준다.
let firstName = "";
let lastName = "";
let nickName = "바이올렛";

alert( firstName || lastName || nickName || "익명"); // 바이올렛
  • 모든 변수가 falsy라면 "익명"이 출력될 것이다.
  1. 단락 평가
  • OR 연산자 ||가 제공하는 또 다른 기능은 ‘단락 평가 (short circuit evaluation)‘이다.
  • OR 연산자 ||는 왼쪽부터 시작해서 오른쪽으로 평가를 진행하는데, truthy를 만나면 나머지 값들은 건드리지 않은 채 평가를 멈춘다. 이런 프로세스를 ‘단락 평가’라 한다.
  • 단락 평가의 동작 방식은 두 번째 피연산자 변수 할당과 같은 부수적인 효과(side effect)를 가지는 표현식일 때 볼 수 있다.
true || alert("not printed");
false || alert("printed");
  • 위의 코드를 실행하면 두 번째 메세지만 출력된다. 첫 번째 줄의 || 연산자는 true를 만나자마자 평가를 멈추기 때문에 alert가 실행되지 않는다.
  • 단락 평가는 왼쪽 조건이 falsy일 때만 명령어를 실행하고자 할 때 자주 쓰인다.

3. && (AND)

  • 두 개의 앰퍼샌드를 연달아 쓰면 AND 연산자 &&를 만들 수 있다.
result = a && b;
  • 전통적인 프로그래밍 방식에서 AND 연산자는 두 피연산자가 모두 참일 때 true를 반환한다. 그 외의 경우는 false를 반환한다.
alert( true && true );   // true
alert( false && true );  // false
alert( true && false );  // false
alert( false && false ); // false
  • if문과 AND 연산자를 함께 활용한 예
let hour = 12;
let minute = 30;

if (hour == 12 && miniue == 30) {
	alert('현재 시각은 12시 30분입니다.');
}
  • OR 연산자와 마찬가지로 AND 연산자의 피연산자도 타입에 제약이 없다.
if (1 && 0) { // 피연산자가 숫자형이지만 논리형으로 바뀌어 true && false가 된다.
  alert( "if 문 안에 falsy가 들어가 있으므로 alert창은 실행되지 않는다." );
}

4. 첫 번째 falsy를 찾는 AND 연산자 ‘&&’

  • AND 연산자와 피연산자가 여러 개인 경우도 있다.
result = value1 && value2 && value3;
  • AND 연산자 &&는 아래와 같은 순서로 동작한다.
    • 가장 왼쪽 피연산자로부터 시작해 오른쪽으로 나아가며 피연산자를 평가한다.
    • 각 피연산자는 불린형으로 변환된다. 변환 후 값이 false이면 평가를 멈추고 해당 피연산자의 변환 전 원래 값을 반환한다.
    • 피연산자 모두가 평가되는 경우(모든 피연산자가 true로 평가되는 경우)에는 마지막 피연산자가 반환된다.
  • AND 연산자는 첫 번째 falsy를 반환한다. 피연산자에 falsy가 없다면 마지막 값을 반환한다. OR 연산자의 알고리즘과 유사하지만, AND 연산자가 첫 번째 falsy를 반환하는 반면, OR 연산자는 첫 번째 truthy를 반환한다.
// 첫 번째 피연산자가 truthy -> AND는 두 번째 피연산자 반환
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// 첫 번째 피연산자가 falsy -> AND는 첫 번째 피연산자 반환 (두 번째 피연산자는 무시)
alert( null && 5 ); // null
alert( 0 && "아무거나 와도 상관없습니다." ); // 0
  • AND 연산자에도 피연산자 여러 개를 연속해서 전달할 수 있다.
alert( 1 && 2 && null && 3 ); // null
  • 피연산자가 모두 truthy이면 마지막 피연산자가 반환된다.
alert( 1 && 2 && 3 ); // 마지막 값, 3

&&||의 우선순위

  • AND 연산자 &&의 우선순위는 OR 연산자 ||보다 높다.
  • a && b || c && d(a && b) || (c && d)와 동일하게 동작한다.

if로 ||&& 대체하기

  • 개발자들은 AND 연산자 &&if문을 ‘짧게’ 줄이는 용도로 사용하곤 하는데, &&를 사용한 코드가 더 짧긴 하지만 if문을 사용한 예시가 코드에서 무엇을 구현하고자 하는지 더 명백히 드러내고, 가독성도 좋다.
  • &&의 오른쪽 피연산자는 평가가 && 우측까지 진행되어야 실행된다. 아래의 경우, (x > 0)이 참인 경우에만 alert문이 실행된다.
let x = 1;

(x > 0) && alert( '0보다 큽니다!' );
  • 위의 코드를 if 문을 써서 바꾸면 아래와 같다.
let x = 1;

if (x > 0) alert( '0보다 큽니다!' );

5. ! (NOT)

  • 논리 연산자 NOT은 느낌표 !를 써서 만들 수 있다.
result = !value;
  • NOT 연산자는 인수를 하나만 받고, 다음의 순서대로 연산을 수행한다.
    • 피연산자를 불린형(true/false)으로 변환한다.
    • 1에서 변환된 값의 역을 반환한다.
alert( !true ); // false
alert( !0 ); // true
  • NOT을 두 개 연달아 사용(!!)하면 값을 불린형으로 변환할 수 있다. 이때, 첫 번째 NOT 연산자는 피연산자로 받은 값을 불린형으로 변환한 후 이 값의 역을 반환하고, 두 번째 NOT 연산자는 첫 번째 NOT 연산자가 반환한 값의 역을 반환한다.
alert( !!"non-empty string" ); // true
alert( !!null ); // false
  • 내장 함수 Boolean을 사용하면 !!를 사용한 것과 같은 겨로가를 도출할 수 있다.
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
  • NOT 연산자의 우선순위는 모든 논리 연산자 중에서 가장 높기 때문에 &&||보다 먼저 실행된다.

6. 과제

다음 OR 연산의 결과는?

아래 코드의 결과를 예측해보세요.

alert( null || 2 || undefined );
  • 풀이
// 피연산자 중 첫 번째 truthy가 출력된다.
alert( null || 2 || undefined ); // 2 출력

OR 연산자의 피연산자가 alert라면?

아래 코드의 결과를 예측해 보세요.

alert( alert(1) || 2 || alert(3) );
  • 풀이
    • alert는 값을 반환하지 않는다 → undefined 반환
    • 첫 번째 OR ||은 왼쪽 피연산자인 alert(1)을 평가하는데, 이때 첫 번재 얼럿 창에 1이 출력된다.
    • alert메서드는 undefined를 반환하기 때문에, OR 연산자는 다음 피연산자를 평가한다.
    • 두 번째 피연산자(오른쪽 피연산자)인 2는 truthy이기 때문에 실행이 멈추고 2가 반환된다.
    • 반환된 값 2는 제일 바깥 alert의 피연산자가 되어 두 번째 얼럿창에 출력된다.
    • 평가가 alert(3)까지 진행되지 않기 때문에 3은 출력되지 않는다.
    • 따라서 얼럿 창엔 1, 2가 차례대로 출력된다.

다음 AND 연산의 결과는?

아래 코드의 결과를 예측해 보세요.

alert( 1 && null && 2 );
  • 풀이
// 피연산자 중 첫 번째 falsy가 출력된다.
alert( 1 && null && 2 ); // null

AND 연산자의 피연산자가 alert라면?

아래 코드의 결과를 예측해 보세요.

alert( alert(1) && alert(2) );
  • 풀이
  • alert를 호출하면 undefined가 반환된다. alert는 단순히 얼럿 창에 메세지만 띄워주고, 의미 있는 값을 반환하지 않는다.
  • &&는 왼쪽 피연산자를 평가하는데, 이때 1이 얼럿창에 출력된다. alert(1)의 평가 결과는 undefinedfalsy이다. && 연산자는 falsy를 만나면 그 값을 출력하고 즉시 연산을 멈춘다.
  • 따라서 얼럿 창엔 1, undefined가 차례대로 출력된다.

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

아래 코드의 결과를 예측해 보세요.

alert( null || 2 && 3 || 4 );
  • 풀이
    • AND 연산자 &&의 우선순위는 ||보다 높다. 따라서 &&가 먼저 실행된다.
    • 2 && 3 = 3이므로, 문제에서 제시한 표현식은 null || 3 || 4와 바꿔 쓸 수 있다.
    • 따라서 첫 번째 truthy인 3이 출력된다.

사이 범위 확인하기

age(나이)가 14세 이상 90세 이하에 속하는지를 확인하는 if문을 작성하세요.

“이상과 이하”는 age(나이) 범위에 14나 90이 포함된다는 의미입니다.

  • 풀이
let age;

if (age >= 14 && age <= 90)

바깥 범위 확인하기

age(나이)가 14세 이상 90세 이하에 속하지 않는지를 확인하는 if문을 작성하세요.

답안은 NOT ! 연산자를 사용한 답안과 사용하지 않은 답안 2가지를 제출해 주세요.

  • 풀이(! 연산자 사용 O)
let age;

if (!(age >= 14 && age <= 90))
  • 풀이(! 연산자 사용 X)
let age;

if(age < 14 || age > 90)

“if”에 관한 고찰

아래 표현식에서 어떤 alert가 실행될까요?

if(...) 안에 표현식이 있으면 어떤 일이 일어날까요?

if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
  • 풀이
if (-1 || 0) alert( 'first' ); // 'first'
// -1 || 0 의 결과는 -1이므로 truthy

if (-1 && 0) alert( 'second' ); // alert 실행 X
// -1 && 0 의 결과는 0이므로 falsy

if (null || -1 && 1) alert( 'third' ); // 'third'
// null || -1 && 1 -> null || 1 -> 1

로그인 구현하기

프롬프트(prompt) 대화상자를 이용해 간이 로그인 창을 구현해보세요.

사용자가 "Admin"를 입력하면 비밀번호를 물어보는 프롬프트 대화상자를 띄워주세요. 이때 아무런 입력도 하지 않거나 Esc를 누르면 “취소되었습니다.”라는 메시지를 보여주세요. 틀린 비밀번호를 입력했다면 “인증에 실패하였습니다.”라는 메시지를 보여주세요.

비밀번호 확인 절차는 다음과 같습니다.

  • 맞는 비밀번호 “TheMaster”를 입력했다면 “환영합니다!”라는 메시지를 보여주세요.
  • 틀린 비밀번호를 입력했다면 “인증에 실패하였습니다.”라는 메시지를 보여주세요.
  • 빈 문자열을 입력하거나 입력을 취소했다면 “취소되었습니다.”라는 메시지를 보여주세요.

중첩 if 블록을 사용하고, 코드 전체의 가독성을 고려해 답안을 작성하세요.

힌트: 프롬프트 창에 아무것도 입력하지 않으면 빈 문자열인 ''가, ESC를 누르면 null이 반환됩니다.

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

if (userName == "Admin") {
	let password = prompt("비밀번호?",'');
	
	if (password == "TheMaster") {
		alert("환영합니다.!");
	} else if (pass == '' || pass == null) {
		alert("취소되었습니다.");
	} else {
		alert("인증에 실패하였습니다.");
	}	

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