Posts 코어 자바스크립트 #2.11: 논리연산자
Post
Cancel

코어 자바스크립트 #2.11: 논리연산자

출처: https://ko.javascript.info/logical-operators

논리 연산자

자바스크립트엔 세 종류의 논리 연산자 ||(OR), &&(AND), !(NOT)이 있다. 연산자에 ‘논리’라는 수식어가 붙지만 논리 연산자는 피연산자로 불린형뿐만 아니라 모든 타입의 값을 받을 수 있다. 연산 결과 역시 모든 타입이 될 수 있다.

|| (OR)

전통적인 프로그래밍에서 OR 연산자는 불린값을 조작하는 데 쓰인다. 인수 중 하나라도 true이면 true를 반환하고, 그렇지 않으면 false를 반환하는 것이다.

1
2
3
4
alert( true || true );   // true
alert( false || true );  // true
alert( true || false );  // true
alert( false || false ); // false

피연산자가 불린형이 아니면, 평가를 위해 불린형으로 변환된다. OR 연산자 ||은 주어진 조건 중 하나라도 인지를 테스트하는 용도로 if문에서 자주 사용된다.

첫 번째 truthy를 찾는 OR 연산자 ‘||’

자바스크립트에서만 제공하는 논리연산자 OR의 ‘추가’기능에 대해 알아보자.

OR 연산자와 피연산자가 여러 개인 경우:

1
result = value1 || value2 || value3;

이때, OR ||연산자는 다음 순서에 따라 연산을 수행한다.

  • 가장 왼쪽 피연산자부터 시작해 오른쪽으로 나아가며 피연산자를 평가한다.
  • 각 피연산자를 불린형으로 변환한다. 변환 후 그 값이 true이면 연산을 멈추고 해당 피연산자의 변환 전 원래 값을 반환한다.
  • 피연산자 모두를 평가한 경우(모든 피연산자가 false로 평가되는 경우)엔 마지막 피연산자를 반환합니다.

여기서 핵심은 반환 값이 형 변환을 하지 않은 원래 값이라는 것이다.

OR "||" 연산자를 여러 개 체이닝(chaining) 하면 첫 번째 truthy를 반환한다. 피연산자에 truthy가 하나도 없다면 마지막 피연산자를 반환한다.

1
2
3
4
5
6
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 연산자의 추가 기능을 이용하면 여러 용도로 OR 연산자를 활용할 수 있습니다.

  1. 변수 또는 표현식으로 구성된 목록에서 첫 번째 truthy 얻기

    OR ||을 사용하면 실제 값이 들어있는 변수를 찾고, 그 값을 보여줄 수 있다. 변수 모두에 값이 없는 경우(falsy)엔 익명를 보여준다.

    1
    2
    3
    4
    5
    
    let firstName = "";
    let lastName = "";
    let nickName = "바이올렛";
       
    alert( firstName || lastName || nickName || "익명"); // 바이올렛
    
  2. 단락 평가(short circuit evaluation)

    위에서 설명해 드린 바와 같이 OR||은 왼쪽부터 시작해서 오른쪽으로 평가를 진행하는데, truthy를 만나면 나머지 값들은 건드리지 않은 채 평가를 멈춘다.

    단락 평가의 동작 방식은 두 번째 피연산자가 변수 할당과 같은 부수적인 효과(side effect)를 가지는 표현식 일 때 명확히 볼 수 있다.

    1
    2
    
    true || alert("not printed"); // 출력X
    false || alert("printed"); // 출력
    

    단락 평가는 연산자 왼쪽 조건이 falsy일 때만 명령어를 실행하고자 할 때 자주 쓰인다.

&& (AND)

전통적인 프로그래밍에서 AND 연산자는 두 피연산자가 모두가 참일 때 true를 반환하고, 그 외에는 false를 반환한다.

1
2
3
4
alert( true && true );   // true
alert( false && true );  // false
alert( true && false );  // false
alert( false && false ); // false

OR 연산자와 마찬가지로 AND 연산자의 피연산자도 타입에 제약이 없다.

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

AND 연산자 &&는 아래와 같은 순서로 동작한다.

  • 가장 왼쪽 피연산자부터 시작해 오른쪽으로 나아가며 피연산자를 평가한다.
  • 각 피연산자는 불린형으로 변환된다. 변환 후 값이 false이면 평가를 멈추고 해당 피연산자의 변환 전 원래 값을 반환한다.
  • 피연산자 모두가 평가되는 경우(모든 피연산자가 true로 평가되는 경우)엔 마지막 피연산자가 반환된다.

AND 연산자는 첫 번째 falsy를 반환한다. 피연산자에 falsy가 없다면 마지막 값을 반환한다. 위 알고리즘은 OR 연산자의 알고리즘과 유사하다. 차이점은 AND 연산자가 첫 번째 falsy를 반환하는 반면, OR은 첫 번째 truthy를 반환한다는 것이다.

1
2
3
4
5
6
7
8
9
// 첫 번째 피연산자가 truthy이면,
// AND는 두 번째 피연산자를 반환한다.
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// 첫 번째 피연산자가 falsy이면,
// AND는 첫 번째 피연산자를 반환하고, 두 번째 피연산자는 무시한다.
alert( null && 5 ); // null
alert( 0 && "아무거나 와도 상관없습니다." ); // 0

AND 연산자에도 피연산자 여러 개를 연속해서 전달할 수 있다.

1
alert( 1 && 2 && null && 3 ); // null

AND 연산자의 피연산자가 모두 truthy이기 때문에 마지막 피연산자가 반환된다.

1
alert( 1 && 2 && 3 ); // 마지막 값, 3

&&의 우선순위가 ||보다 높다.

따라서 a && b || c && d(a && b) || (c && d)와 동일하게 동작한다.

**if 나 &&로 대체하지 말자.**

어떤 개발자들은 AND 연산자 &&if문을 ‘짧게’ 줄이는 용도로 사용하곤 한다.

1
2
3
4
5
6
let x = 1;

(x > 0) && alert( '0보다 큽니다!' ); 
// 왼쪽 피연산자 평가 후 참이면 오른쪽 피연산자 실행

if (x > 0) alert( '0보다 큽니다!' ); //이 if문과 같다.

&&를 사용한 코드가 더 짧긴 하지만 if문을 사용한 예시가 코드에서 무엇을 구현하고자 하는지 더 명백히 드러내고, 가독성도 좋다. 그러니 if 조건문이 필요하면 if를 사용하고 AND 연산자는 연산자 목적에 맞게 사용하자.

! (NOT)

NOT 연산자는 인수를 하나만 받고, 다음 순서대로 연산을 수행한다.

  1. 피연산자를 불린형(true / false)으로 변환한다.
  2. 1에서 변환된 값의 역을 반환한다.
1
2
alert( !true ); // false
alert( !0 ); // true

NOT을 두 개 연달아 사용(!!)하면 값을 불린형으로 변환할 수 있다.

1
2
alert( !!"non-empty string" ); // true
alert( !!null ); // false

내장 함수 Boolean을 사용하면 !!을 사용한 것과 같은 결과를 도출할 수 있다.

1
2
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false

NOT 연산자의 우선순위는 모든 논리 연산자 중에서 가장 높기 때문에 항상 &&|| 보다 먼저 실행된다.

과제

Q1. 다음 OR 연산의 결과는 무엇일까요?

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

1
alert( null || 2 || undefined );

해답: 2

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

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

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

해답: alert 창에 1과 2가 출력된다.

alert 메서드는 값을 반환하지 않는다. 즉 alert(1)은 undefined를 반환한다. undefined는 falsy이기 때문에 다음 피연산자를 평가한다. 2는 truthy이기 때문에 실행을 멈추고 2를 반환한다. 반환된 값 2는 바깥 alert의 피연산자가 되어 두 번째 알림창에 출력된다.

Q3. 다음 AND 연산의 결과는 무엇일까요?

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

1
alert( 1 && null && 2 );

해답: null 첫 번째 falsy 값 리턴

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

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

1
alert( alert(1) && alert(2) );

해답: 알림창으로 1이 출력되고 undefined가 출력된다.

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

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

1
alert( null || 2 && 3 || 4 );

해답: 3이 출력된다.

연산자 우선순위 때문에 2&&3이 먼저 평가된다. 마지막까지 truthy한 값이니 마지막 값인 3이 반화된다. 그리고 null || 3 || 4를 평가한다. 3이 첫 truthy한 값이니 3을 반환한다.

Q6. 사이 범위 확인하기

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

해답:

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

Q7. 바깥 범위 확인하기

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

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

해답:

1
2
if (age >= 14 && age )
if (!(age <= 14 || age >= 90))

Q8. “if”에 관한 고찰

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

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

1
2
3
if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );

해답: first, third가 출력된다.

Q9. 로그인 구현하기

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

1
2
3
4
5
6
7
8
9
10
11
12
13
let userName = prompt("Who's there?");
if (userName == "Admin") {
  password = prompt("Passwrod?")
  if (password == "TheMaster")
    alert("Welcome!");
  else if (password == '' || password == null)
    alert("Canceled.");
  else
    alert("Wrong password");
} else if (userName == '' || userName == null)
  	alert("Canceled");
	else
  	alert("I don't know you");
This post is licensed under CC BY 4.0 by the author.

:book: 자바의 정석 #8: 예외처리

:book: 자바의 정석 #9.1: java.lang 패키지

Loading comments from Disqus ...