[모던 JavaScript 튜토리얼] 2.9 비교 연산자

모던 JavaScript 튜토리얼을 읽고 정리하였습니다.

비교 연산자

자바스크립트에서 기본 수학 연산은 아래와 같은 문법을 사용해 표현이 가능하다.

  • a > b, a < b
  • a >= b, a <= b
  • a == b
  • a != b

문자열 비교

자바스크립트는 사전 순으로 문자열을 비교하며 이 비교 기준을 사전편집(lexicographical)순이라고 부른다. 즉. 사전 뒤쪽의 문자열은 사전 앞쪽의 문자열보다 큰다고 판단된다.

실제 단어를 사전에 실을 때의 등재 순서와 동일하게 문자열을 구성하는 문자 하나하나를 비교해가며 비교한다.

alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true

문자열 비교 시 적용되는 알고리즘은 다음과 같다.

  • 두 문자열의 첫 글자를 비교한다.
    • 한 문자열의 첫 글자가 다른 문자열의 첫글자보다 클 경우, 그 문자열을 다른 문자열보다 크다고 결론 지은 후, 비교를 종료한다.
    • 두 문자열의 첫 글자가 같으면 두 번째 글자를 같은 방식으로 비교한다.
  • 글자 간 비교가 끝날 때까지 위의 과정을 반복한다.
  • 어느 한쪽이 크다는 결론이 나지 않고 한 문자열의 끝 글자까지 모두 비교했다면
    • 문자열의 길이가 같을 경우 두 문자열은 동일하다고 결론 짓는다.
    • 문자열의 길이가 다를 경우, 길이가 긴 문자열이 더 크다고 결론 짓는다.

문자열 비교 알고리즘

자바스크립트의 문자열 비교 알고리즘은 사전에서 사용되는 정렬 알고리즘과 유사하나, 정확히는 사전 순이 아니라 유니코드 순이라고 할 수 있다. 사전과 유니코드의 차이점은 자바스크립트는 대·소문자를 따진다는 것이다. 따라서 “A”와 “a”를 비교했을 때, 소문자 “a”더 크다.


다른형을 가진 값 간의 비교

비교하려는 값의 자료형이 다르면 자바스크립트는 이 값들을 숫자형으로 바꾼다.

alert( '2' > 1 ); // true
alert( '01' == 1 ); // true 

불린 값의 경우 true는 1, false는 0으로 변환된 후 비교가 이뤄진다.

alert( true == 1 ); // true
alert( false == 0 ); // true

다음과 같은 두 상황에서는 다른 결과를 리턴

let a = 0;
alert(Boolean(a)); // false

let b = "0";
alert(Boolean(b)); // true

alert(Boolean(a) == Boolean(b)); // false

alert(a == b); // true

a와 b를 불린값으로 형 변환 해준 후에 비교하면 거짓이 반환되지만, a와 b를 바로 비교하면 true가 반환된다. 바로 비교 연산자를 사용하게 될 경우에는 b를 숫자형으로 형변환해준 상태에서 두 값을 비교하기 때문이다.


일치 연산자

동등 연산자(equality operator) ==은 0과 false를 구별하지 못한다. 동등 연산자가 형이 다른 피연산자를 비교할 때 피연산자를 숫자형으로 바꾸기 때문이다.

alert( 0 == false ); // true

피연산자가 빈 문자열일 떄도 같은 문제가 발생한다. 빈문자열과 false는 숫자형으로 변환되면 모두 0이 되기 때문이다.

alert( '' == false ); // true

그런데 일치 연산자(Strict Equality Operator) === 을 사용하면 형 변환 없이 값을 비교할 수가 있다. 일치 연산자는 한마디로 엄격한 동등 연산자이다. 자료형의 동등 여부까지 검사하므로 피연산자 a와 b의 형이 다를 경우 a === b는 false를 즉시 반환한다.

alert( 0 === false ); // false

마찬가지로 불일치 연산자 !==는 부등 연산자 !=의 엄격한 형태이다.


null이나 undefined 비교하기

일치 연산자 ===를 사용

두 값의 자료형이 다르기 때문에 일치 비교 시 거짓이 반환된다.

alert(null === undefined); // false

동등 연산자 ==를 사용

동등 연산자를 사용해 nullundefined를 비교하면 특별한 규칙이 적용돼 true가 반환된다.

alert(null == undefined); // true

산술 연산자나 기타 비교 연산자를 사용

nullundefined는 숫자형으로 변환되어 비교된다. 즉, null0, undifinedNaN으로 변한다.

null vs 0

alert(null > 0); // false
alert(null == 0); // false
alert(null >= 0); // true

세번째 줄에서 null은 0보다 크거나 같은데, 첫번째 줄과 두번째에서 모두 거짓을 반환한다는 모순적인 결과를 도출했다. 이는 동등 연산자 ==와 기타 비교 연산자의 동작 방식이 다르기 때문이다. 첫번째줄과 세번쨰 줄은 ==를 제외한 비교 연산자로, null이 숫자형으로 변환되어 0이 된다. 그런데 두번째 줄에서 ==는 피연산자가 undefined나 나 null일 때 형 변환을 하지 않는다. undefined나 null을 비교하는 경우에만 true를 반환하고 그 이외의 경우(null이나 undefined를 다른 값과 비교할 때)는 무조건 false를 반환한다. 따라서 두번째 줄에서 거짓이 반환되는 것이다.

비교가 불가능한 undefined

undefined는 다른 값과 비교해서는 안된다.

alert( undefined > 0 ); // false
alert( undefined < 0 ); // false
alert( undefined == 0 ); // false

undefined는 계속해서 false를 반환하고 있다. 이유는 다음과 같다.

  • 첫번째 줄과 두번째 줄에서 undefinedNaN으로 변환되는데(숫자형으로의 변환), NaN이 피연산자인 경우 비교 연산자는 항상 false를 반환한다.
  • undefinednull이나 undefined와 같고, 그 이외의 값과는 같지 않기 때문에 세번째 줄은 false를 반환한다.

함정 피하기

당장 이러한 예제를 암기할 필요는 없지만 아래와 같은 방법을 사용해 예외상황을 미리 예방할 수가 있다.

  • 일치 연산자 ===를 제외한 비교 연산자의 피연산자에 undefinednull이 오지 않도록 주의한다.
  • 또한 undefinednull이 될 가능성이 있는 변수가 ==, ===이외의 비교 연산자로 연산되지 않도록 주의한다.

Comments