느슨한/엄격한 동등 비교
느슨한 동등비교는 ==
연산자를, 엄격한 동등비교는 ===
연산자를 각각 사용한다. 두 연산자 모두 두 값의 '동등함'을 비교하지만 '느슨함'과 '엄격함'이라는 아주 중요한 차이점이 있고 특히 동등함의 판단 기준이 다르다.
많은 이들이 종종 "==
는 값의 동등함을, ===
은 값과타임 모두의 동등함을 비교한다"라고 오해한다. 그럴듯 하지만 정확하진 않다. 엄청나게 많은 자바스크립트 책들에 그렇게 씌어있지만 불행하게도 다 틀렸따.
정확한 정의를 내려보자. "동등함의 비교 시 ==
는 강제변환을 허용하지만, ===
는 강제변환을 허용하지 않는다"
비교 성능
전자의 정의와 후자의 정의를 잠시 음미해보자.
전자에 의하면 ===
는 타입까지 체크하므로 ==
에 비해 할일이 많다. 후자에 따르면 오히려 타입이 다를 경우 강제변환을 해야 하므로 ==
가 더 할일이 많다.
하지만 마치 ==
이 ===
보다 눈에 띄게 처리가 더뎌서 어떤 식으로든 성능에 영향을 미치는 것처럼 생각하진 말자. 강제변환 시 처리 시간이 약간 더 소요되긴 하지만, 불과 몇 마이크로 초단위의 차이일 뿐이다.
타입이 같은 두 값의 동등 비교라면, ==
와 ===
의 알고리즘은 동일하자. 엔진의 내부 구현 방식은 조금씩 다를 수도 있지만, 기본적으로 하는 일은 같다.
타입이 다른 두 값의 동등비교에서 성능은 중요한 포인트가 아니다. 우리가 자문해봐야 할 사항은 비교 과정에서 강제변환의 개입 여부이다.
강제변환이 필요하다면 느슨한 동등 연산자를, 필요하지 않다면 엄격한 동등 연산자를 사용하자.
어짜피 == 든 === 든 피연산자의 타입을 체크하는 건 매한가지이다. 다른 점은 타입이 다를 대 이후 처리 로직이다.
추상 동등 비교
==
연산자 로직은 ES5 11.9.3추상적 동등비교 알고리즘에 상술되어 있다. 잡다한 항목이 나열되어 있지만 알고리즘 자체는 간단하다. 모든 가능한 타입별 조합마다 (필요시)강제변환을 어떻게 수행하는지 그 방법이 적혀있다.
(암시적)강제변환을 곱지 않게 보는 사람들이 가장 일반적으로 비난하는 대상이 바로 이 추상적 동등 관련 규칙이다. 너무 난해하여 개발자들이 실제로 배우고 사용하기에 직관적이지 못할 분 아니라 자바스크립트 코드의 가독성을 향상하지는 못할망정 버그만 양산하는 규칙들이라고 주장한다. 하지만 이런 부정적인 생각은 명세를 읽는 독자가 알고리즘만 전문으로 개발하는 노련한 개발자여야 한다는 잘못된 가정에 근거한 사실이다. 실제로 추상적 동등 규칙은 쉬운 용어로 평이하게 기술되어 있다.
일단 첫번째 항에는 이렇게 씌어있다. 비교할 두 값이 같은 타입이면 누구나 예상하듯이 값을 식별하여 간단히, 자연스럽게 견주어 본다. 예컨대 42와 동등한 값은 42뿐이고 "abc"와 동등한 값은 "abc"이다.
다음 예외는 사소하나마 상식을 벗어나므로 주의해야 한다.
- NaN은 그 자신과도 결코 동등하지 않다.
- +0와 -0은 동등하지 않다.
- 11.9.3.1의 마지막 항목에서는 객체(함수와 배열 포함)의 느슨한 동등 비교에 대해 두 객체가 정확히 똑같은 값에 대한 레퍼런스 일 경우에만 동등하다고 기술되어 있다. 여기서 강제변환은 일어나지 않는다.
11.9.3.6을 보면 엄격한 동등 비교 === 역시 두 객체 값 비교 방법에 대해 똑같이 기술되어 있다. 객체의 동등 비교에 있어서 == 와 === 의 로직이 똑같다는 사실은 거의 알려저 있지 않다.
11.9.3 알고리즘 나머지 부분에서는 타입이 다른 두 값을 느슨한 동등비교시, 한쪽 또는 양쪽 피연산자에서 암시적 강제변환을 어떻게 해야 하는지 씌어 있다. 결과적으로 두 값의타입을 일치시켜 간단히 값만 보고 비교하기 위함이다.
짐작하겠지만, 느슨한 비동등 연산자 != 의 결괏값은 == 연산자의 동등 비교 수행 후 그 결과를 그대로 부정한 값이다. 엄격한 비동등 연산자 !== 도 마찬가지이다.
'JAVASCRIPT' 카테고리의 다른 글
[JS][강제변환] 동등비교 : null -> undefined, 객체 -> 비객체 (0) | 2022.02.12 |
---|---|
[JS][강제변환] 동등비교 : 문자열 -> 숫자, * -> 불리언 (0) | 2022.02.12 |
[JS][강제변환] 암시적 강제변환 : * -> 불리언, || 와 && 연산자 (0) | 2022.02.11 |
[JS][강제변환] 암시적 강제변환 : 불리언 -> 숫자 (0) | 2022.02.11 |
[JS][강제변환] 암시적 강제변환 : 문자열 <-> 숫자 (0) | 2022.02.11 |
댓글