자바스크립트의 형 변환(type conversion)과 비교 연산

5 == '5'

이 표현식의 결과는 true가 나옵니다. 왜 그럴까요?

자바스크립트에서 두개의 '='인 '=='을 이용한 비교는 좌변과 우변의 값을 바로 비교하지 않고 자동으로(강제적으로) 자료형을 변환하고 비교를 수행합니다. 이를 묵시적 형변환이라고 합니다. 그리고 '=' 기호를 두 개 사용한 비교를 느슨한 동등 연산자라고 합니다. 느슨한 동등 연산에서는 자바스크립트가 자료형을 일치 시키기 위해 오른쪽의 자료형을 왼쪽과 일치하도록 만들어 줍니다. 위의 식에서는 문자열 '5'가 숫자 5로 변환되는 것이죠.

 

항상 오른쪽 자료형을 왼쪽 자료형과 일치시키는 것은 아닙니다. 그저 비교가 가능한 값으로 바꾸는 것이죠. 그래서 다음과 같은 상황도 가능합니다. 다음 상황에서는 양쪽 모두 false로 변환되었을 것입니다.

"" == 0 // true

 

동등 연산자뿐만아니라 비교 연산자에서도 위와 같은 현상이 일어납니다.

5 > '3' //true

위의 코드는 숫자와 문자열의 크기를 비교하고 있음에도 오류가 아닌 true를 반환합니다. 비교 연산에서는 항상 숫자로 변경하기 때문이죠. 이는 앞의 값과 같은 자료형으로 만들어주는 느슨한 동등 연산자와는 다른 부분입니다.

숫자와 문자열의 변환 외에도 Bool 값, 문자열끼리 값을 비교할 때도 묵시적 형변환이 발생합니다. false는 0, true 1로 취급하고, 문자열끼리의 비교에서는 문자열을 유니코드로 변환한 뒤 비교를 수행합니다. 따라서 다음과 같은 연산도 가능합니다.

false + 1 // 1

'a' < 'b' // true

 

문자열끼리의 비교를 할때는 앞에 있는 문자를 먼저 비교합니다. 만약 비교한 문자의 크기가 같다면 다음 문자를 비교하여 크기를 비교합니다. 그런데 가장 마지막의 예시처럼 N번째까지 문자열이 일치하면 더 긴 문자열이 큰 값을 가집니다.

'abc' > 'b' // false
'c' > 'avc' // true

'abc' < 'abd' // true

'abcd' > 'abc' // true

만약 유니코드를 알고 싶다면 '유니코드를 알고 싶은 문자'.charCodeAt()을 사용하면 됩니다. 그리고 문자열과 숫자를 비교할 때는 유니코드가 아닌 문자열을 직접 숫자로 변경하려고 합니다. 그래서 문자열은 NaN(Not a Number)가 되어 문자와 숫자의 대소 비교는 항상 false가 됩니다. NaN과의 비교는 항상 false를 반환하기 때문입니다.

'a' > 8 // false
'a' < 8 // false

숫자와 문자의 덧셈

묵시적 형변환은 가끔 의도치않은 결과를 만들 수 있습니다. 자바스크립트에서 숫자와 문자의 덧셈 연산은 문자열로 변환한 뒤 수행하도록 만들어져 있습니다. 문자열에서의 덧셈 연산은 숫자와는 달리 두 개의 문자열을 이어 붙이는 것이죠. 따라서 다음과 같은 동작이 수행됩니다.

'1' + 2 // 12
3 + '4' // 34

 

다만 뺄셈과 나눗셈 및 곱셈은 숫자로 형변환을 하여 계산합니다. 계산하려는 값이 모두 문자열이라도 말이죠. 그래서 숫자로 변환할 수 없는 값을 뺄셈이나 나눗셈 및 곱셈으로 계산하면 NaN이 나오게 됩니다.

'5' - 3 // 2
'15' / '5' // 3
'a' * 3 // NaN

엄격한 동등 연산

자바스크립트가 모든 비교에서 자동 형변환을 강제적으로 수행한다면 의도치 않은 결과가 나올 수 있습니다. 예를 들어 문자열 1'과 숫자 1을 비교하면 같은 값이라고 알려주는 것처럼 말이죠. 다행히 자바스크립트에서는 자료형까지 비교할 수 있는 엄격한 비교를 제공합니다. 바로 엄격한 동등 연산자라고 불리는 3개의 '=' 기호를 사용하는 것이죠.

5 === '5'

이 표현식은 true가 아닌 false를 반환합니다. 엄격한 비교를 통해 자료형의 일치하는지 여부를 검사하기 때문이죠. 하지만 '>=='처럼 크기를 비교하는 연산을 수행할 수는 없습니다. 에러가 발생합니다.

논리연산

자바스크립트의 Boolean

자바스크립트에서 비교 혹은 논리 연산을 수행할 때 Bool 값이 false가 나오는 값들은 오직 6개만 존재합니다.
false, 0, ''(빈 문자열), null, undefined, NaN, (여기에 더해 document.all)의 6개입니다(document.all은 사용할 일이 없다고 보아도 무방하므로 앞의 6개만 알고 있어도 충분합니다.). 그 외의 모든 값은 Boolean으로 변환 시 true를 반환합니다. 어떤 값의 진리값을 쉽게 알아보려면 앞에 !!를 붙여주면 됩니다(!은 다른 언어들 처럼 반전된 Bool값을 만들어줍니다.). 혹은 Boolean함수를 사용해도 됩니다.

주의!: Boolean 객체는 불리언 값을 감싸고 있는 객체이기 때문에 생성자(new 키워드)를 이용해 평가되어 나오는 값은 항상 ture인 값을 가집니다.

단락 평가(단축평가)

자바스크립트는 다른 프로그래밍 언어와 마찬가지로 단락평가를 지원합니다. 논리연산은 왼쪽부터 수행되는데, and(&&) 연산은 false를 찾을 때까지, or(||) 연산은 true를 찾을 때까지 연산을 수행합니다. 각각의 논리적은 특성으로 and는 하나라도 false가 있으면 전체가 false이므로 false로 평가되는 표현식을 찾는 즉시 연산을 종료하고 해당 표현식을 반환합니다. or은 정확히 반대이죠. 이를 통해 코드를 간소화 할 수있습니다. 만약 state라는 변수가 isReady라는 값이 true일 때만 'start'를 가지도록 하고 싶으면 다음과 같이 코드를 작성할 수 있습니다.

const state = isReady && 'start'

만약 isReady가 false라면 state는 false가 되죠.

또 다른 연산들

빈 값인지 확인하여 평가하기

그리고 널 병합 연산자('??')라는 것이 있습니다. or 연산이 true로 표현되는 첫번째 값을 반환하는 것과 달리 왼쪽 피연산자가 null 또는 undefined일 때 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환하는 연산자입니다.

leftExpr ?? rightExpr;

만약 leftExpr가 null이나 undefined일 때 rightExpr를 반환하고 다른 값을 가진다면 leftExpr를 반환합니다.

객체 내부의 값 찾기

자바스크립트에는 Optional chaining(?.)이라는 연산자가 존재하는데요. 속성 접근자(.)을 통해 접근하는 객체의 속성에서 왼쪽의 값이 존재한다면 오른쪽의 값이 참조하는 값에 접근합니다. 즉 왼쪽의 값이 null이나 undefined가 아니라면 참조하는 값에 접근하고 null이나 undefined라면 그 값(null 또는 undefined)을 반환합니다. 따라서 참조가 누락될 가능성이 있는 경우 연결된 속성으로 접근할 때 더 짧고 간단한 표현식으로 해당 값에 접근할 수 있습니다.

참고자료

MDN, [표현식과 연산자, 동등 비교 및 동일성 ]
모던 JavaScript 튜토리얼, 형 변환

+ Recent posts