[Javascript] 비교 연산자
📌 참고 사이트
비교 연산자
ko.javascript.info
📋 기본적인 비교 연산자
기본 수학 연산은 아래와 같은 문법을 사용해 표현할 수 있다.
➡️ ~보다 큼 : a > b, ~보다 작음 : a < b
➡️ ~보다 크거나 같음 : a >= b, ~보다 작거나 같음 : a <= b
➡️ 같음(동등): a == b (등호가 하나(=)일때는 할당을 의미한다.)
➡️ 같지 않음(부등): a != b
자바스크립트에서의 비교 방법과 기이한 현상에 대해 알아볼 것이다.
📋 불린형 반환
➡️ 비교 연산자 역시 다른 연산자와 마찬가지로 값을 반환한다. 그 반환 값은 불린형이다.
➡️ true가 반환되면 참(긍정), false가 반환되면 거짓(부정)을 의미한다.
console.log(2 > 1); // true (참)
console.log(2 == 1); // false (거짓)
➡️ 반환된 불린값은 변수에 할당하는 것이 가능하다.
let result = 5 > 4; // 비교 결과인 true를 변수 result에 할당한다.
console.log(result); // true
📋 문자열 비교
➡️ 자바스크립트는 유니코드 순으로 문자열을 비교한다. 이것은 사전(편집)순이라고도 불리며, 사전 뒤쪽의 문자열이 사전 앞쪽의 문자열보다 크다고 판단된다.
→ a쪽으로 갈수록 더 작은 것이 되고, z쪽으로 갈수록 더 큰 것이 된다.
→ 소문자가 대문자보다 더 큰 것이 된다. (유니코드에서 소문자가 대문자보다 더 큰 인덱스를 가진다.)
<문자열 비교 시 적용되는 알고리즘>
1️⃣ 두 문자열의 첫 글자를 비교한다.
2️⃣ 첫 번째 문자열의 첫 글자가 다른 문자열의 첫 글자보다 크면, 첫 번째 문자열이 두 번째 문자열보다 크다고 결론 내고 비교를 종료한다. 작을 때는 첫 번째 문자열이 더 작다고 결론 내고 비교를 종료한다.
3️⃣ 두 문자열의 첫 글자가 같으면 두 번째 글자를 같은 방식으로 비교한다.
4️⃣ 글자 간 비교가 끝날 때까지 위 과정을 반복한다.
5️⃣ 비교가 종료되었고 문자열의 길이도 같다면 두 문자열은 동일하다고 결론낸다. 비교가 종료되었지만 두 문자열의 길이가 다르면 길이가 긴 문자열이 더 크다고 결론낸다.
console.log('Z' > 'A'); // true
console.log('Glow' > 'Glee'); // true
console.log('Bee' > 'Be'); // true
📋 다른 형을 가진 값 간의 비교
➡️ 비교하려는 값의 자료형이 다르면 자바스크립트는 그 값들을 숫자형으로 바꾼다.
→ 불린값의 경우 true는 1, false는 0으로 변환된 후 비교가 이루어진다.
alert( '2' > 1 ); // true, 문자 '2'가 숫자 2로 변환 후 비교 진행
alert( '01' == 1 ); // ture, 문자 '01'이 숫자 1로 변환 후 비교 진행
console.log(true == 1); // true
console.log(false == 0); // true
➡️ 다음과 같이 동시에 일어나지 못할 것 같은 상황이 동시에 일어나는 경우도 있다.
→ 동등 비교(==) 시 true를 반환
→ 그런데 각각 논리 평가 시 값 하나는 true, 다른 값 하나는 false를 반환하는 경우
let a = 0; // Number형
console.log(Boolean(a)); // false
let b = "0"; // String형
console.log(Boolean(b)); // true
console.log(a == b); // true (왜 그럴까?)
숫자 0을 불리언형으로 변환하면 거짓이 되므로 false가 반환되고, 문자 "0"은 비어 있지 않은 문자열에 해당하므로 불리언형으로 변환하면 참이 되어 true가 반환된다.
그런데 이 두 변수 a와 b를 동등 연산자(==)로 비교하면 같다는 의미의 true가 나온다.
이는 동등 비교 연산자(==)는 숫자가 아닌 피연산자("0")를 숫자형(0)으로 바꾸어 비교하지만, Boolean을 이용한 불리언으로의 명시적 형 변환에서는 다른 규칙(숫자의 경우 0이면 false, 문자열의 경우 빈 문자열이 아니면 true)이 사용되기 때문이다.
📋 일치 연산자
➡️ 앞서 살펴보았듯이 동등 연산자(==, equality operator)는 0과 ""와 false를 구분하지 못한다. 따라서 0, "", false 모두 동등 연산자로 비교하면 같은 것(true)로 나온다.
→ 동등 연산자가 형이 다른 피연산자를 비교할 때 피연산자를 숫자형으로 바꾸기 때문이라고 하였다.
console.log(0 == false); // true
console.log('' = false); // true
➡️ 일치 연산자(===, strict equality operator)를 사용하면 형 변환 없이 있는 그대로의 값 비교가 가능하다.
→ 일치 연산자는 '엄격한' 동등 연산자이기 때문에 자료형의 동등 여부까지 검사한다.
→ 즉, 값이 같아도 자료형이 다르면 false를 반환한다.
→ 위의 원리대로, 불일치 연산자(!==)는 부등 연산자(!=)의 엄격한 버전이다.
→ 일치 연산자는 동등 연산자보다 비교 결과가 명확하므로 에러가 발생할 확률을 줄여준다.
console.log(0 === false); // false (피연산자의 형이 다르기 때문에)
📋 null이나 undefined와 비교하기
null이나 undefined를 다른 값과 비교 시 예상치 않은 일들을 볼 수 있다.
📍 일치 연산자(===)를 사용하여 null과 undefined를 비교
두 값의 자료형이 다르기 때문에 일치 비교 시 거짓(false)이 반환된다.
console.log(null == undefined); // false
📍 동등 연산자(==)를 사용하여 null과 undefined 비교
null과 undefined를 각각 숫자로 변환하면 0과 NaN이 되어 false가 될 것 같지만, 위와 같은 경우 동등 연산자는 null과 undefined를 특별한 쌍으로 인식하여 true로 반환된다. 두 값끼리는 잘 어울리지만 다른 값하고는 어울리지 못한다.
console.log(null == undefined); // true
📍 산술 연산자나 기타 비교 연산자 <, >, <=, >=를 사용하여 null과 undefined를 비교
산술 연산자나 기타 비교 연산자를 사용하여 null과 undefined를 비교하려 하면 그 둘은 숫자형으로 변환된다. null과 undefined를 각각 숫자로 변환하면 0과 NaN이 된다고 하였다. 이 둘을 비교한 결과는 항상 false가 나올 수밖에 없다.
📍 null vs 0
null과 0의 크기를 비교한 결과는 다음과 같다.
console.log(null > 0); // 1. false
console.log(null == 0); // 2. false
console.log(null >= 0); // 3. true
첫번째와 두번째가 거짓이면 세번째도 거짓으로 나와야 하는데 참으로 나왔다.
이는 동등 연산자(==)와 기타 비교 연산자(<, >, <=, >=)의 동작 방식이 다르기 때문이다.
1️⃣ null > 0에서는 기타 비교 연산자가 사용되었고, 동작 원리에 따라 null이 숫자형으로 변환되므로 0 > 0은 거짓이어서 false가 반환된다.
2️⃣ 동등 연산자(==)가 쓰였는데, 동등 연산자는 피연산자가 undefined이거나 null일 경우 형 변환을 하지 않는다. 따라서 특별한 경우인 undefined == null 의 경우를 제외하고 모두 false를 반환한다. (null이나 undefined를 서로나 자기 자신이 아닌 다른 값과 비교할 경우)
3️⃣ 기타 산술 연산자인 >=가 쓰였으므로 null이 숫자인 0으로 변환된다. 0 >= 0은 성립하므로 true가 반환된다.
📍 비교가 불가능한 undefined
console.log(undefined > 0); // 1. false
console.log(undefined == 0); // 2. false
console.log(undefined < 0); // 3. false
1️⃣ 과 3️⃣ 기타 산술 연산자가 사용되었으므로 undefined가 숫자형으로 변환되어 NaN이 된다. 따라서 항상 false를 반환한다. (NaN이 피연산자이므로)
2️⃣ undefined는 null이나 undefined하고만 같고(==에서 true) 그 이외의 값과는 같지 않다.
💡 함정을 피하기 위해서는 일치 연산자(===)를 제외한 비교 연산자의 피연산자에 undefined나 null이 오지 않게 주의해야 한다. (둘이 될 가능성이 있는 것들도 오지 않게 주의!)
만약 변수가 undefined나 null이 될 가능성이 있다고 판단되면 이를 따로 처리하는 코드를 추가하는 것이 좋다.
✏️ 과제
📍 아래 표현식들의 결과를 예측해라.
5 > 4 // 1. true
"apple" > "pineapple" // 2. false
"2" > "12" // 3. true
undefined == null // 4. true
undefined === null // 5. false
null == "\n0\n" // 6. false
null === +"\n0\n" // 7. false
1️⃣ 숫자끼리의 비교 : 5가 4보다 크므로 당연히 true
2️⃣ 문자열끼리의 비교 : 'apple'의 첫 글자인 'a'는 'pineapple'의 첫 글자인 'p'보다 작으므로 false (사전순)
3️⃣ 문자열끼리의 비교(숫자로 변환 X!) : 유니코드 상 왼쪽의 첫 글자인 '2'는 오른쪽의 첫 글자인 '1'보다 크다. (역시 사전순)
4️⃣ 동등 연산자를 이용한 비교 : null == undefined는 특별한 한 쌍이라고 하였으므로 true
5️⃣ 일치 연산자를 이용한 비교 : null과 undefined는 형이 다르므로 false
6️⃣ 동등 연산자를 이용한 비교 : null은 == 이용 시 오직 undefined하고만 같다. 다른 것이 오면 false
7️⃣ 일치 연산자를 이용한 비교 : null과 +"\n0\n" (0이 됨.)은 형이 다르므로 false