본문 바로가기

프론트엔드/JavaScript

자바스크립트 암묵적 타입 변환(Implicit Coercion)

자바스크립트 암묵적 타입 변환(Implicit Coercion)

타입 변환이란? (명시적 타입 변환 vs 암묵적 타입 변환)

명시적 타입 변환: 개발자가 의도적으로 타입을 변환하는 것. 타입 캐스팅(Type Casting) 이라고도 함.
암묵적 타입 변환: 개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동으로 변환되는 것. 타입 강제 변환(Type Coercion)이라 한다.

명시적 타입 변환은 타입을 변경하겠다는 개발자의 의지가 코드에 명백히 드러나지만, 암묵적 타입 변환은 그렇지 않다. 타입 변환 결과를 예측하지 못한다면 오류를 생산할 가능성이 높아진다. 그래서 이에 대해 잘 이해하고 예측 가능한 코드를 작성하는 것이 중요하다.

암묵적 타입 변환

암묵적인 데이터 변환의 예

console.log("10" + 1); // '101'
console.log(10 * "10"); // 100

첫번째 라인은 피연산자가 모두 문자열이 아님에도 문자열을 더한 것 같은 결과가 나타난다.

두번째 라인은 피연산자가 모두 숫자여야 하는 결과가 출력된다.

문자열 타입으로 변환

위에서 봤듯이 '+' 연산자는 피연산자 중 하나가 문자열이면 문자열 연결 연산자로 동작한다.

console.log(10 + "10"); // 1010

아래의 코드도 문자열 연결 연산자로 동작한 결과를 확인할 수 있다.

console.log(2 + "1" + 5); // 2715
console.log(2 + 7 + "1" + 5); // 주의 : 이 결과는 915다.

두번째도 전체가 다 문자열 연결로 동작할까? 하고 테스트를 해보았는데 앞에 2 + 7은 숫자 연산으로 처리된다.
문자열 타입으로 암묵적 변환이 이루어지는 추가적인 예시는 아래와 같다.

0 + '' // '0'
-0 + '' // '0'
NaN + 'a' // NaNa
Infinity + '' // 'Infinity'
-Infinity + '' // '-Infinity'

true + ' ' + false + '' // 'true false'

[] + '' // ''
[1,2] + '' // '1,2'

Symbol() + '' // TypeError

이 외에 궁금한 것이 있다면 직접 해보면서 확인해보면 좋을 것 같다. 마지막에 Symbol()은 string 타입으로 변환할 수 없다.

숫자 타입으로 변환

'+' 단항 연산자는 피연산자가 숫자 타입의 값이 아니면, 숫자 타입의 값으로 암묵적으로 타입 변환을 수행한다.

+'' // 0
+'0' // 0
+'1' // 1
+'hello' // NaN

+true // 1
+false // 0

+null // 0
+[] // 0
+[1,2] // NaN
+function(){} // NaN

불리언 타입으로 변환

if, for문과 같은 제어문의 조건식은 참 혹은 거짓으로 평가되어야 하는 표현식이다. 자바스크립트 엔진은 조건식의 평가 결과를 불리언 타입으로 암묵적 타입 변환한다.

if ("") console.log("test1");
if (true) console.log("test2");
if (0) console.log("test3");
if ("a") console.log("test4");
if (null) console.log("test5");

// test2
// test4

=> 자바스크립트 엔진은 불리언 타입이 아닌 값을 Truthy(참으로 평가되는 값) 또는 Falsy(거짓으로 평가되는 값)으로 구분한다.

  • false로 평가되는 값 : false, undefined, null, 0, -0, NaN, ''
  • true로 평가되는 값 : false가 아닌 모든 값. {}, [] 와 같은 것들도 모두 true로 평가됨.

느낀점

+'3'과 같이 숫자가 아닌 데이터 타입의 앞에 단항 연산자 '+'를 붙이면 숫자로 변환이 될 수 있다는 점은 전혀 몰랐다. 또한 NaN이 Falsy 값인 것도 이번에 공부하면서 처음 알게됐다. 가끔 자바스크립트를 사용하면서 내가 원하는 결과가 나오지 않았을 때, 타입이 일치하지 않는 경우가 있었는데, 앞으로는 그런 실수를 줄일 수 있을 것 같다.

[], {} 와 같은 같은 녀석들은 Falsy값인 줄 알았는데, Truthy값이라는 것도 꽤 충격이었다. 지금이라도 알게되서 다행이다. 보통 배열이 비어있을 때 arr.length === 0와 같은 방식으로 코드를 작성했는데, 이번에 공부하지 않았다면 언젠가는 한번쯤 if(arr) {...} 이런식으로 코드를 작성할 수도 있었겠네? 라는 생각이 든다.

확실히 지식을 쌓는 과정은 흥미롭다. 그러나 포스팅은 꽤나 귀찮다. 하지만 내가 한번 더 생각하면서 글로 정리하는 편이, 더 기억에도 오래남고 이해하는 것에도 도움이 되는 느낌이다.

다음 포스트는 명시적 타입 변환에 대한 내용을 작성할 계획이다.



틀린 내용이 있다면 댓글로 알려주시면 감사하겠습니다!