[JavaScript] &&(AND)연산자와 ||(OR)연산자
js는 다른 언어들과는 다르게 동작하는 연산들이 많이 있다.
오죽하면 이런 밈이 유행할 정도인데...
이번 포스트에서 다룰 것은 AND연산자와 OR연산자다.
불 연산
컴퓨터나 이공계를 전공했다면 '불 대수'에 대해 들어본 적이 있을 것이다.
불 대수에서, A AND B (A와 B는 참이거나 거짓)의 결과값은 항상 참이거나 거짓이다.
마찬가지로, C나 JAVA같은 강타입 언어에서 불 연산을 진행하면 값 역시 반드시 boolean 값으로 나오게 된다.
그런데 js에서의 논리 연산의 결과값은 boolean 값을 가질 수도 있지만, 다른 값을 가질 수도 있다.
const test= "first" && "second";
console.log(typeof test === 'boolean'); //false
분명 && 연산을 했지만, 결과값은 불 타입이 아니다.
const test= "first" && "second"; //test === "second"
console.log(typeof test === 'boolean'); //false
console.log(typeof test === 'string'); //true
왜냐하면, test에 들어간 값은 "second"가 되어서 test의 타입은 string이 되기 때문이다.
그렇다면 어떤 원리로 결과값이 정해지는 걸까?
기본적인 원리 자체는 다른 언어와 다르지 않다.
잠시 불 연산이 컴퓨터에서 어떻게 이루어지는지 알아보자.
불 연산 최적화
let _first= 0;
let _second= 0;
const first= ()=>{
_first++;
return true;
}
const second= ()=>{
_second++;
return true;
}
console.log(first() || second());
console.log(_first, _second); //1, 0
먼저 위 코드를 보자.
first() || second()에서 js 엔진은 가장 먼저 first()의 값을 평가한다.
first()의 값이 true 이므로 true와 어떤 값을 OR연산 하더라도 결과값은 true이므로, 후위값은 연산할 필요가 없게 되고 실제로도 연산하지 않는다.
따라서 second()는 아예 호출되지 않으며, console.log(_first, _second)의 출력값은 1, 0이 된다.
let _first= 0;
let _second= 0;
const first= ()=>{
_first++;
return true;
}
const second= ()=>{
_second++;
return true;
}
console.log(first() && second());
console.log(_first, _second); //1, 1
그런데 AND연산자는 두 값이 모두 참일때만 결과값이 참이 된다.
즉 first()가 true일지라도, second()값에 따라 결과값이 달라지므로 first() || second()와는 달리
second()의 값까지 알아야만 해당 연산의 결과값을 알 수 있게 된다.
두 값을 모두 평가해야 하므로, console.log(_first, _second)의 출력값은 1, 1이 된다.
let _first= 0;
let _second= 0;
const first= ()=>{
_first++;
return false;
}
const second= ()=>{
_second++;
return true;
}
console.log(first() && second());
console.log(_first, _second); //1, 0
그런데 만약 first()가 false를 리턴한다면 어떻게 될까?
false 와 어떤 값을 AND 연산하더라도 결과값은 false가 되므로 뒤의 값은 연산할 필요가 없다.
따라서 console.log(_first, _second)의 출력값은 1,0이 된다.
불 연산 최적화랑 무슨 상관이 있나?
const test= "first" && "second"; //test === "second"
불 연산 최적화를 유의하면서, 다시한번 위 코드를 보자.
test의 값을 계산하는 과정에서
"first" && "second"를 평가할 때, "first"는 null이 아니므로 true처럼 동작한다.
위에서 설명한 대로 AND연산 시, 하나의 값이 true더라도 나머지 값에 따라서 결과값이 달라질 수 있으므로 뒤따라오는 식도 평가해야 한다.
따라서 "second"를 평가하게 되고, test에는 마지막으로 평가한 값인 "second"가 들어간다.
그렇다.
javascript에서 논리 연산자는 마지막으로 평가한 값 자체를 결과값으로 취급한다.
console.log("first" || null); //"first"
console.log(null || "first"); //"first"
console.log("first" && null); //null
console.log(null && "first"); //null
console.log("first" || "second"); //"first"
console.log("first" && "second"); //"second"
해당 내용을 위의 코드에 적용시켜본다면 한층 빠르게 이해할 수 있을 것이다.
코드에 적용
const users= [
{name: '김김김', id: 'admin'},
{name: '이이이', id: 'sfgbnzbnzzz'}
];
const findUser= (id)=>{
return users.find(user=> user.id === id);
};
const guest= {
name: '게스트',
id: 'guest',
};
const user1= findUser('testId') || guest; //testId라는 유저가 없으므로 user에 guest가 할당됨
const user2= findUser('admin') || guest; //admin이라는 유저는 존재하므로 {name: '김김김', id: 'admin'}이 할당됨
이런 식으로, 어떤 값이 null 일때의 기본값을 지정하는데 사용되기도 하고
(삼항 연산자를 사용할 때 보다 코드의 가독성이 높다)
const Example= ()=>{
const [data, setData]= useState();
useEffect(()=>{
setTimeout(()=>{
setData('hello world');
}, 1000);
}, []);
return (
<div>
{
data && <h3>데이터 값: {data}</h3>
}
</div>
);
}
리액트에서 && 연산자를 활용하여, 원하는 데이터가 null이 아닐때만 엘리먼트를 표시할 때도 사용한다.