015. [기본] 논리 연산자(or &&, !not, 논리 연산자 우선순위)
복습이 목적이라면 이 문서에서 연습문제 먼저 보는 것이 좋다. 연습문제의 품질이 좋다.
논리 연산자
논리 연산자 | 기능 | 의미 |
---|---|---|
|| | OR(원화표시) | 이항 중 하나라도 참이면 true, 아니면 false |
&& | AND | 이항 중 둘 다 참이어야 true, 아니면 false |
! | NOT | 부호를 반대로 뒤집음 |
|| (OR) 연산자
|| 연산자 기본형
result = a || b;
a와 b 중 하나라도 true면 true를 반환하고, 아니면 둘 다 fasle면 false를 반환한다.
예시
console.log( true || true ); // true
console.log( true || false ); // false
console.log( false || true ); // true
console.log( false || false ); // false
주로 if문에서 많이 사용된다.
if ( 1 || 0 ) {
console.log("truthy!");
} // truthy!
// 1은 truhty한 값, 0은 falsy한 값이다. 따라서 둘 중 하나가 true이므로 if의 조건문이 참이 되어 평가된다.
여러개도 중첩 가능하다.
let hour = 12;
let isWeekend = true;
if ( hour < 10 || hour > 18 || isWeekend ) {
console.log( '영업시간이 아닙니다.' );
}
// hour가 10보다 작거나, hour가 18보다 크거나, isWeekend(주말인 상태)가 true이면
// 조건문이 실행되도록 했다.
// 10시 오픈, 18시 클로즈여서 그렇고, hour는 12로 영업시간이 맞지만, isWeekend 변수가 true 상태이므로
// 셋 중 하나라도 true이기 때문에 코드 블럭이 실행된다.
정리하자면 || 논리 연산자는 피연산자가 2개일 때와 3개 이상일 때 반환하는 값이 다르다.
- 피연산자가 2개 일 때
- 피연산자 중 truthy한 값이 하나라도 있으면 true를 반환하고, 둘 다 falsy한 값이라면 false를 반환한다.
- 피연산자가 3개 이상일 때
- 왼쪽부터 오른쪽으로 차례대로 피연산자를 비교해나간다.
- truty한 값이 먼저 나오는 값의 원래의 값을 반환한다.
- 만약 모두 falsy한 값이면 가장 마지막 피연산자의 원래의 값을 반환한다.
|| 논리 연산자의 추가 기능
첫번째 truthy한 값을 찾는 ||
위의 예제는 || 논리 연산자가 불린값들만 놓고 각 항에서 true나 truthy한 값이 하나라도 있으면 true를 반환하는 예제였다.
하지만 자바스크립트에서만 동작하는 추가 기능이 있다. 피연산자가 불린형이 아닌 경우에는 좌항부터 차례대로 비교해가며 가장 먼저 등장하는 truthy한 값을 반환한다.
|| 논리 연산자의 추가 기능 알고리즘
- 좌항에서부터 우측으로 진행하며 비교를 시작한다. (chaning)
- 첫번째 항과 두번째 항을 비교한다.
- 각 피연산자를 불린형으로 변환해서 truthy한 값이 나오면 그 값의 원래 값을 반환한다.
- 만약 피연산자가 모두 falsy한 값일 경우 가장 마지막 피연산자를 반환한다.
console.log( 1 || 0 ); // 1
// 1은 truthy, 0은 falsy한 값이다.
// 따라서 truthy한 값인 1을 반환한다.
console.log( null || 1 ); // 1
// 1은 역시 truthy한 값이다.
console.log( null || 0 || 1 ); // 1
console.log( undefined || null || 0 ); // 0
// 모두 falsy한 값이기 때문에 마지막 값인 0을 반환한다.
|| 논리 연산자의 실제 사용 예시
- 변수 또는 표현식으로 구성된 목록에서 첫번째 truthy한 값 얻기 (회원정보 등에서 공백이 없이 실제 데이터가 있는 값을 반환시키기)
let firstName = "";
let lastName = "";
let nickName = "바이올렛";
console.log( firstName || lastName || nickName || "정보없음"); // 바이올렛
객체 유저정보를 통해 값 얻기(직접 작성)
객체, 프로퍼티 호출법, 템플릿 리터럴 등에 대한 지식이 있어야 한다.
let user = {
firstName : "",
lastName : "",
nickName : "바이올렛"
};
let message = `
${user.firstName || user.lastName || user.nickName || "익명"} 회원님 안녕하세요!
`;
console.log(message); // 바이올렛 회원님 안녕하세요!
단락평가 (short circuit evaluation)
단락평가라는 것은 || 논리 연산자가 피연산자를 왼쪽부터 오른쪽으로 truthy한 값을 찾아 비교를 진행하다가,
truthy한 값을 찾게 되면 더이상 비교를 진행하지 않고 멈추는 것을 말한다.
true || console.log("안녕하세요"); // 작동안함
false || console.log("안녕하세요"); // 안녕하세요
&& (AND) 연산자
&& 연산자 기본형
두 개의 앰퍼샌드를 연달아 쓰면 AND 연산자 &&를 만들 수 있다.
result = a && b;
피연산자가 모두 참일 때 true를 반환한다. 그 외의 경우에는 false를 반환한다.
예시
console.log( true && true ); // true
console.log( true && false ); // false
console.log( false && true ); // false
console.log( false && false ); // false
&& 논리 연산자의 실제 사용 예시
let hour = 12;
let minuet = 30;
if (hour == 12 && minuet == 30) {
console.log( '현재 시각은 12시 30분입니다.' );
}
if (1 && 0) {
console.log('hello');
} // 작동하지 않음
// 0은 무조건 false이기 때문에 둘 다 truthy가 되어야만 true를 반환하는 && 연산자는 false를 반환한다.
첫번째 falsy한 값을 찾는 &&
|| (OR) 논리 연산자는 피연산자를 왼쪽부터 비교해가며 가장 먼저 등장하는 truthy한 값의 원래 값을 반환했다.
그런데 && (AND) 논리 연산자는 좌항이 true면 우항을 반환하고, 좌항이 false면 좌항을 반환한다.
&& 논리 연산자의 추가 기능 알고리즘
- 가장 왼쪽의 피연산자부터 싯작해 오른쪽으로 나아가며 피연산자를 평가한다.
- 각 피연산자는 불린형으로 변환된다. 변환된 값이 falsy한 값이 나오면 평가를 멈추고 해당 피연산자의 원래 값을 반환한다.
- 피연산자를 모두 평가했는데 모두 truthy한 값이 나오는 경우 마지막 피연산자를 반환한다.
console.log( 1 && 0 ); // 0
console.log( 1 && 5 ); // 5
console.log( null & 5 ); // null
console.log( 0 && "문자열" ); // 0
- 추가적으로 && 연산자도 여러 개 중첩해서 사용할 수 있다.
- &&와 ||가 동시에 사용되는 경우 &&가 우선순위가 높다.
console.log( 1 && 0 || 0 && "hello" ); // 0
// 위 식은 아래와 같다.
console.log( ( 1 && 0 ) || ( 0 && "hello" ));
console.log( 1 && 2 && 3 ); // 3
console.log( 1 && 2 && null && 3 ); // null;
// 1과 2 비교 : 1이 참이기 때문에 2 반환
// 2와 null 비교 : 2가 참이기 때문에 null 반환
// null과 3 비교 : null이 거짓이기 때문에 null 반환
&& 연산자를 if문 대체용으로 사용하지 말 것
&& 연산자는 피연산자를 왼쪽에서 오른쪽으로 차례대로 비교하면서 좌항이 참이면 우항을 반환한다는 특징 때문에 이를 if문을 대체해서 사용이 가능하다. 하지만 이처럼 사용하면 가독성이 떨어지기 때문에 권장하지 않는다.
// 부적절한 예시
let x = 1;
(x > 0) && console.log('0보다 큽니다!');
// 적절한 예시
let x = 1;
if (x > 0) {console.log('0보다 큽니다!')};
! (NOT) 연산자
논리 연산자 ! 는 앞에 붙이면 피연산자를 불린형으로 변환한 뒤 그 값을 반대로 뒤집는다.
console.log( !true ); // false
console.log( !0 ); // true
!!를 두 번 쓰면 '아니다의 아니다'가 된다. 즉 원상태다. 굳이 이것을 쓰는 이유는 ! 논리 연산자를 사용할 때 피연산자를 불린형으로 형 변환하는 특성을 사용하기 위해서이다. 즉 Boolean()이라는 형 변환 함수를 대체 가능하다.
console.log( !!'안녕하세요' ); // true
console.log( !!null ); // false
논리 연산자의 우선순위
! -> && -> || 순으로 높다.
정리
논리 연산자 | 반환 값 |
---|---|
&& | 좌항이 true면 우항 반환, false면 반대 |
|| | 좌항이 true면 좌항 반환 |
이 부분은 암기의 영역인 것 같다. 며칠 지나면 또 헷갈린다.
올바른 학습방법인지는 모르겠으나, 나는 이렇게 이해하고자 한다.
- && 연산자는 if문을 대체할 수 있는 연산자이다. if문은 조건식이 참이면 우측으로 진행하는 성질이 있기 때문에 && 연산자 또한 좌항이 참이면 우측으로 진행한다고 이해된다.
그리고 || 연산자는 truthy한 값을 찾아다닌다고 이해된다.
- && 연산자는 false를 찾아 다닌다. && 연산자는 피연산자가 여러개일 때 왼쪽부터 순서대로 비교하다가 false가 나오면 그 falsy한 값의 원래의 값을 반환하고 비교를 종료한다.
- || 연산자는 true를 찾아 다닌다. || 연산자는 피연산자가 여러개일 때 왼쪽부터 순서대로 비교하다가 true가 나오면 그 truth한 값의 원래 값을 반환하고 비교를 종료한다.
이게 왜 이렇게까지 안 외워지나 싶지만... 익숙해질 때까지는 연상법을 사용해야겠다...
'(오티)에 (엔에프)소나타를 타고...'
논리 연산자 | 전체식 반환 값 |
---|---|
&& | (and '그리고') 모든 피연산자가 truthy한 값이어야 전체식을 true로 반환 |
|| | (or '또는') 피연산자 중 하나라도 truthy한 값이면 전체식을 true로 반환 |
연습문제
- 아래 코드의 결과는?
console.log( null || 2 || undefined );
- 아래 코드의 결과는?
alert( alert(1) || 2 || alert(3) );
- 아래 코드의 결과는?
console.log( 1 && null && 2 );
- 아래 코드의 결과는?
alert( alert(1) && alert(2) );
- 아래 코드의 결과는?
console.log( null || 2 && 3 || 4 );
- age가 14세 이상, 90세 이하에 속하는지 확인하는 if문을 작성하시오.
- age가 14세 이상, 90세 이하에 속하지 않는지를 확인하는 if문을 작성하시오. (! 연산자를 사용한 답안과 사용하지 않은 답안 두 개를 작성하시오.)
- 아래 표현식에서 어떤 alert가 실행될 것인지 예측해보시오.
if (-1 || 0) alert( 'first' ); if (-1 && 0) alert( 'second' ); if (null || -1 && 1) alert( 'third' );
- 로그인창 구현하기 문제는 원문에서 확인.
해답
- 2
- &&는 좌항이 true면 우항 반환, ||는 좌항이 true면 좌항 반환.
- 첫번째 비교인 null과 2의 비교에서 좌항이 false이기 때문에 우항 반환.
- 그런데 우항이 2로 truthy한 값이기 때문에 2를 반환하고 비교 종료.
- alert창에 1, 2가 차례대로 출력된다.
- alert 메서드는 값을 반환하지는 않는다. 즉 undefined 상태이다. undefined는 falsy한 값이다.
- 일단 alert는 메서드이기 때문에 코드가 실행된다. 그리고 undefined와 2를 비교한다. undefined는 falsy한 값이기 때문에 || 연산자는 좌항이 true면 좌항을 반환하는데 반대의 경우기 때문에 우항을 검사한다. 그런데 우항이 숫자 2로 truthy한 값이기에 2를 반환하고 연산은 종료된다.
- 즉 alert에서 1을 실행하라는 코드가 실행되고, () 소괄호 안에서 비교를 하다 2라는 값에서 비교 연산을 멈추고 2라는 값을 반환했기에 큰 코드블럭인 alert(2)까지 실행되어 실제 alert 창에는 1과 2가 연달아 출력된다. alert(3)의 평가는 이루어지지 않고 그 앞에서 멈췄다.
- null
- 1과 null을 비교한다. || 연산자는 좌항이 true면 우항을 반환한다. 좌항이 숫자 1로 true이기 때문에 null을 반환한다. false가 나왔으므로 비교를 종료하고 null을 반환한다.
- alert창에 1, undefined가 차례대로 출력된다.
- alert 메서드는 값이 없고 undefined이다. 일단 1항의 alert(1)의 코드가 실행되어 alert창에는 1이 출력된다.
- 그리고 undefined는 falsy한 값이기에 false를 찾아 다니는 || 연산자는 비교를 멈춘다. 그리고 좌항의 값인 undefined를 반환한다.
- 1항에서 이미 falsy한 값이 나왔기 때문에 우항은 진행되지 않고 비교도 진행되지 않는다.
- 3
- 이 문제가 헷갈리는 이유는, ||, && 논리 연산자가 함께 쓰였을 때 논리 연산자의 우선순위가 존재하기 때문이다. 왼쪽에서부터 오른쪽으로 진행하는 것은 같은 연산자만 사용됐을 때의 이야기다.
- 논리 연산자의 우선순위는 ! > && > || 순이다.
- 즉 이 문제에선 2 && 3부터 비교한다. && 연산자는 falsy한 값을 찾는다. 둘 다 숫자로 truthy한 값이므로, && || 연산자 모두 둘 다 truthy하거나 falsy한 값이면 우항을 반환한다. 즉 여기선 3이 반환된다.
- 그리고 다시 같은 연산자인 || 연산자만 남았으므로 좌측부터 순서대로 비교를 진행한다.
- null || 3의 비교가 진행된다. null은 falsy한 값, 숫자 3은 truty한 값이므로 || 연산자는 truthy한 값을 찾는다는 목적을 달성했다. 따라서 3을 반환하고 뒤의 비교는 진행되지 않고 멈춘다.
- 해답
- && 비교 연산자는 falsy한 값을 찾는 논리 연산자이다. 좌항과 우항에서 falsy한 값을 찾아야 하는데, 둘 다 truty한 값이면 true를 반환한다.
- 크게는 if문이기 때문에 () 소괄호 안의 조건식이 true라면 if문은 {} 중괄호 안의 코드를 실행할 것이다. 그러나 피연산자 중 하나라도 falsy면 false를 반환하기 때문에 if문은 더 이상 진행하지 않는다.
- 예를 들어 age에 9라는 값이 할당되었다면, 좌항은 false이지만 우항은 true가 된다. && 연산자는 모두 truty한 값이어야 전체식이 true가 된다. 따라서 하나라도 거짓이니 false를 반환하는 것이다.
if (age >= 14 && age <= 90) {}
- 해답
// ! 연산자 미사용 if (age < 14 || age > 90) {}
// ! 연산자 사용
if ( !(age >= 14 && age <= 90) ) {}
- ! 연산자 미사용
- age < 14 && age > 90이 아닌 이유는 age가 9라고 가정했을 때 14세보다 작으면서 90세 보다 크다는 두 가지 조건을 만족하는 것은 불가능 하기 때문에 둘 중 하나라도 만족하면 참이라고 보는 || 연산자를 사용한 것이다.
- ! 연산자 사용
- '14세 이상이면서 90세 이하인 age'를 먼저 && 연산자로 계산하고 괄호로 묶은 다음 ! 연산자를 넣어 값을 '아니다'의 개념을 추가해 뒤집으면 된다.
8. 'first', 'third' 두 개
- 첫번째 표현식 : -1 || 0 의 비교에서 truthy한 값은 -1이다. -1은 true이므로 이 표현식은 실행된다. 참고로 숫자를 불린형으로 변환할 때 0 제외 나머지 수는 음수이든 양수이든 모두 truthy한 값이다.
- 두번째 표현식 : -1 && 0 의 비교에서는 falsy한 값을 찾아야 하는데, 0이 falsy한 값이므로 0을 반환한다. 따라서 이 조건식은 false가 되므로 표현식이 실행되지 않는다.
- 세번째 표현식 : null || -1 && 1 의 비교에서 &&이 ||보다 우선순위가 높기 때문에 -1 && 1부터 비교한다. &&은 falsy한 값을 찾는데, 둘다 truthy이므로 우항의 값을 반환한다. 따라서 null || 1의 비교가 진행되는데 ||은 truthy한 값을 찾으므로 1을 반환하고 이 조건식은 true가 되어 표현식이 실행된다.
9. 로그인 창 구현하기
```javascript
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( "인증되지 않은 사용자입니다." );
}
'Programing > JavaScript' 카테고리의 다른 글
[모던JS] 017. [기본] while과 for 반복문 (0) | 2024.03.28 |
---|---|
[모던JS] 016. [기본] nullish 병합 연산자 (0) | 2024.03.28 |
[모던JS] 014. [기본] if와 물음표를 사용한 조건 처리(삼항 연산자, 물음표 연산자, 조건부 연산자) (0) | 2024.03.25 |
[모던JS] 013. [기본] 비교 연산자(동등비교, 일치비교, 문자열간비교, null==undefined) (1) | 2024.03.25 |
[모던JS] 012. [기본] 기본 연산자와 수학(산술 연산자, 연산자 우선순위, 할당 연산자, 복합 할당 연산자, 증감 연산자, 전후위형 증감연산자, 비트연산자, 쉼표연산자) (1) | 2024.03.25 |
댓글