일치(===) 연산자 는 비교(==) 연산자 와 같이 좌항과 우항의 값을 비교하는 비교연산자 다.
그렇다면 왜 하나는 '='이 3개이고 나머지 하나는 2개일까?
왜 그런지 알아보고 둘중 어느게 더 좋고, 혹시 문제는 없는지 알아보자.
동등(==) 연산자
동등 (==) 연산자는 좌항과 우항이 동일한지 참 거짓 여부를 판정해주는 연산자다.
일반적으로 아래와 같이 값의 비교를 필요로 하는 경우에 사용되는데 그렇다면 == 연산자만 있어도 충분한거 아닐까 싶지 않을까?
let num1 = 1;
let num2 = 1;
let num3 = 2;
let result1 = num1 == num2 ? true : false;
let result2 = num1 == num3 ? true : false;
console.log(result1);
console.log(result2);
왜 일치(===) 연산이 있는지 알아보기 전 위의 코드의 경우 출력하면 어떤 결과가 나올까?
간단한 연산이라 다들 어렵지 않게 결과값을 알 수 있을거다.
true
false
위 코드는 result 에 num1 과 num2 같은 경우는 true 를 다른 경우는 false 를 선언하는 삼항연산자이다.
여기까지만 보면 === 연산의 존재 이유를 알 수 없다. 그렇다면 아래의 코드는 어떻게 나올지 예상해보자.
let num = 1;
let str = '1';
let result = num == str ? true : false;
console.log(result);
우선 num 에는 1이 할당되어 있고 1의 자료형은 number이다. 다음으로 str 에는 '1이 할당되어 있고 작은따옴표가 붙은것을 통해 이 값은 string 임을 알 수 있다.
두 값은 모두 1을 나타내고 있지만 하나는 number형 이고, 나머지 하나는 string이다. 그렇다면 출력결과는 자료형이 다르기 때문에
이 두 값을 '같다'라고 볼 수 없기에 false 를 출력할 것이다. 출력결과를 보자.
true
???
예상과는 정 반대의 결과가 출력됨을 알 수 있는데 왜 그럴까?
이는 == 연산은 단순 '값'을 비교하기 때문이다. 즉, 좌항과 우항의 값을 비교할 때 타입은 고려하지 않는다는 것이다.
그럴 일은 없지만, string과 number형의 구분이 필요없이 값의 비교만 필요한 경우는 이 연산을 사용해도 문제 없이 잘 작동할 것이다.
하지만, 이런 형태의 연산은 자바스크립트 엔진의 암묵적 형변환으로 인해 나중에 에러가 발생한 경우 에러의 원인을 찾는데 어려움을 줄 수 있다. 그렇기 때문에 이 문제를 해결하기 위해 생긴 것이 일치(===) 연산자 이다.
일치 (===) 연산자
위의 설명에 따르면 동등 연산자에서 생긴 문제를 해결해주는 연산이 일치 연산자라고 했으니 설명하기에 앞서 아래 코드의 출력값이 무엇일지 고민해보자.
let num1 = 1;
let num2 = 1;
let str = '1';
let result1 = num1 === num2 ? true : false;
let result2 = num1 === str ? true : false;
console.log(result1);
console.log(result2);
눈치챘겠지만, 위 코드의 출력 결과는 아래와 같이 출력이 된다.
true
false
동등 연산자는 일치 연산자와 달리 타입에 구애받지 않고 오로지 값의 일치 여부를 판단한다.
하지만, 일치 연산자는 값과 타입의 일치 여부를 판단한다.
그렇기 때문에 같은 1이여도 number인 것과 string 인 것 더 나아가 boolen 값인 true 와의 비교에서도 암묵적 형변환이 이루어지지 않고, 그 때문에 값은 동일하더라도 타입이 일치하지 않으면 false 를 반환하는 것이다.
여기까지만 보면 일치 연산자는 마치 은탄환같아 보인다.
그렇다면 한가지 예시 코드를 더 보자.
let num1 = 100 / 0; // +infinity
let num2 = 100 / (-0) // -infinity
let result1 = num1 === num2 ? true : false;
let result2 = 0 === (-0) ? true : false;
let result3 = NaN === NaN ? true : false;
console.log(result1);
console.log(result2);
console.log(result3);
흔하지 않지만 이런 난해한 코드를 사용해야하는경우 이 출력값은 어떻게 나올까?
우선 result1을 분석해보자.
result1은 infinity와 -infinity 를 비교하는 연산을 진행하여 참 거짓에 따라 true, false를 출력하는 코드이다.
무한대는 같은 무한대 값이지만, 앞에 부호가 +, - 의 차이가 있기 때문에 출력값으로 false 가 나와야할것이다.
result2는 0은 0이여도 음수와 양수 구분 기호가 붙었기 때문에 false가 나오는 것이 예상된다.
result3는 NaN과 NaN의 동등 비교이기 때문에 NaN은 'Not a Number' 의 약어로 숫자가 아님을 표현해주는 값이기 때문에
true가 출력될 것으로 기대된다.
그렇다면 결과를 봐보자.
false
true
false
result1은 예상한대로 값이 나왔는데 나머지 result2 와 result3는 정 반대의 결과가 나온다.
이것은 일치연산자에서는 0과 -0 은 같은 수를 의미하기 때문에 부호의 유무에 관계없이 true를 리턴한다.
또한 NaN은 숫자가 아닌 값을 의미하면서 자신과 일치하지 않는 값의 속성을 갖고있따. 그렇기 때문에 일치연산에서 false를 리턴한다.
하지만, 몇몇 경우에서는 NaN이 나올 경우를 처리해야 할 수 있고, 0이여도 양수와 음수를 나눠야하는 경우가 생길 수 있다.
그런 경우는 어떻게 해야할까?
Object.is() 메서드
ES6에서 도입된 Object.is 메서드는 예측가능한 정확한 비교 결과를 반환한다. 그 외에는 일치 비교 연산자(===)와 동일하게 동작한다.
let result1 = -0 === +0 ? true : false;
let result2 = NaN === NaN ? true : false;
let result3 = Object.is(-0,+0) ? true : false;
let result4 = Object.is(NaN, NaN) ? true : false;
console.log(result1);
console.log(result2);
console.log(result3);
console.log(result4);
비교일치연산에서 다룬 마지막 예시에 따르면 result1과 result2 는 각각 true와 false의 값을 출력할 것이다.
그렇다면 result3과 result4는 어떤 차이가 있을지 출력해보자.
true
false
false
true
result3와 result4는 예상한 값을 출력한다.
즉, 0에 부호가 필요한 경우와 값이 NaN인 경우를 조건문으로 사용해야한다면 Object.is를 사용하면 된다.
NaN은 Number.isNaN() 으로 전용 매서드를 사용 할 수 있다.
참고 자료
표현식과 연산자 - JavaScript | MDN
이번 장에서는 JavaScript의 표현식과 함께 할당, 비교, 산술, 비트 계산, 논리, 문자열, 삼항 등 다양한 연산자를 살펴보겠습니다.
developer.mozilla.org
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/is
Object.is() - JavaScript | MDN
Object.is() 정적 메서드는 두 값이 같은 값인지 결정합니다.
developer.mozilla.org
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
Number.isNaN() - JavaScript | MDN
Number.isNaN() 메서드는 주어진 값이 NaN인지 판별합니다. 기존부터 존재한 전역 isNaN() 함수의 더 엄격한 버전입니다.
developer.mozilla.org
'frontEnd > javaScript' 카테고리의 다른 글
console.log("Hoisting"); (1) | 2024.12.19 |
---|---|
console.log("JavaScript 싱글 스레드"); (2) | 2024.09.03 |
[코린이의 공부] flatMap vs filter,map (지적 환영) (2) | 2023.11.30 |