타입

타입 변환 에서 JavaScript

2개의 연습 문제

타입 변환 소개

JavaScript에서 값은 서로 다른 타입일 수 있어요. 변수의 타입은 명시적인 _타입 변환_으로 바꿀 수 있어요. 그 외에도 JavaScript는 상황이 요구하면 타입 강제 변환(암시적 타입 변환)도 수행해요.

타입 변환

JavaScript에는 다른 많은 언어처럼 (다른) 타입으로 캐스팅하는 구문이 없지만, 대신 몇 가지 내장 도우미를 사용할 수 있어요. 특히 전역 객체인 Boolean, Number, String을 함수처럼 사용해서 값을 해당 타입으로 변환할 수 있어요.

불리언으로 변환하기 (truthy/falsy 값)

Boolean(value)를 사용하면 어떤 값이든 불리언으로 변환할 수 있어요. 어떻게 그렇게 될까요?

false로 변환되는 값들의 집합이 정해져 있는데, 이런 값을 _falsy_라고 해요. 가장 중요한 것은 false, 0, 빈 문자열, null, undefined, NaN이 falsy라는 점이에요. MDN의 "Falsy" 문서에서 전체 목록을 볼 수 있어요.

그 외의 모든 값에 대해서는 Boolean이 true를 반환해요. 이런 값을 _truthy_라고 해요.

Boolean(-1);
// => true

Boolean(0);
// => false

Boolean(' ');
// => true

Boolean('');
// => false

참고로, 방금 설명한 규칙 때문에 '0', 'false', [], {}는 JavaScript에서 truthy예요.

숫자로 변환하기

Number(value)는 값을 숫자로 변환할 때 사용할 수 있어요. 문자열의 앞과 뒤에 있는 공백은 무시되고, 빈 문자열은 0으로 변환돼요. 원시 값이 아닌 값이나 숫자를 나타내지 않는 문자열을 변환하려고 해도 오류가 발생하지 않아요. 대신 결과는 NaN(숫자가 아님)이에요.

Number('  -12.34  ');
// => -12.34

Number('1,2');
// => NaN

Number('1 2');
// => NaN

Number('');
// => 0

Number('10e3');
// => 10000

Number({ key: '123' });
// => NaN

아래에서 다른 원시 값들에 대해 Number가 반환하는 값을 볼 수 있어요.

Number(true);
// => 1

Number(false);
// => 0

Number(null);
// => 0

Number(undefined);
// => NaN

참고로, 마지막 예제와 달리 인자 없이 호출한 Number()는 0을 반환하도록 정의돼 있어요.

JavaScript는 parseInt와 parseFloat 함수도 제공해요. 이 함수들은 어떤 문자열을 숫자로 변환할 수 있는지에 대해 더 느슨한 규칙을 적용해요. 그래서 예상치 못한 결과를 피하려면 변환 함수로는 Number를 사용하는 게 좋아요.

parseInt('123a45');
// => 123

Number('123a45');
// => NaN

문자열로 변환하기

String(value)로 값을 문자열로 변환할 수 있어요. 원시 값이라면 결과는 예상하는 그대로예요.

String(12.34);
// => '12.34'

String(false);
// => 'false'

String(null);
// => 'null'

String(undefined);
// => 'undefined'

배열의 경우, String 함수는 각 원소에 문자열 변환을 적용한 뒤 그 결과를 쉼표로 이어 붙여요. 구분자를 직접 지정하는 등 join 메서드를 직접 사용할 수도 있어요. 다만 이 경우 null과 undefined는 빈 문자열로 변환돼요.

String([42, null, true, 'abc']);
// => '42,,true,abc'

객체의 경우, 기본적으로 String은 별로 도움이 되지 않는 텍스트를 반환해요.

String({ key: 'value' });
// => '[object Object]'

toString 메서드를 제공하는 식으로 변환 동작을 직접 바꿀 수도 있어요. javascript.info의 "객체를 원시 값으로 변환하기" 섹션에서 자세한 내용을 설명해요.

객체와 배열을 더 나은 문자열로 표현하는 또 다른 흔한 방법은 JSON 인코딩을 사용하는 거예요. JSON.stringify로 문자열로 변환하고, JSON.parse로 다시 객체나 배열로 되돌릴 수 있어요.

const obj = {
  name: 'Gilda Guerra',
  address: {
    city: 'Goiânia',
  },
};

JSON.stringify(obj);
// => '{"name":"Gilda Guerra","address":{"city":"Goiânia"}}'

타입 강제 변환

특정한 문맥에서 JavaScript는 어떤 문을 평가하기 전에 값을 다른 데이터 타입으로 자동 변환해요. 이렇게 암시적으로 이루어지는 변환을 _타입 강제 변환_이라고 해요.

불리언 문맥

값이 불리언 문맥에서 사용되면, JavaScript는 Boolean 함수와 같은 규칙을 적용해서 값을 암시적으로 변환해요.

  • if 문의 조건이 불리언이 아니면, 조건이 충족되는지 아닌지를 판단하기 위해 강제 변환이 적용돼요. 삼항 연산자 ?의 첫 번째 피연산자에도 같은 규칙이 적용돼요.

    const num = 0;
    if (num) {
      // this block is NOT executed because 0 is falsy
    }
    
    const name = 'Jin';
    name ? 'name was provided' : 'no name provided';
    // => 'name was provided'
    
  • 논리 NOT 연산자 !의 피연산자도 NOT 연산이 적용되기 전에 불리언으로 강제 변환돼요.

    const name = '';
    !name;
    // => true
    

    이런 동작의 결과로 !!value는 Boolean(value)와 같은 효과를 내요. 그래도 가독성을 위해 Boolean을 사용하는 게 좋아요.

  • JavaScript는 논리 AND(&&)와 OR(||) 연산자의 피연산자에도 강제 변환을 적용해요. 하지만 표현식의 결과가 반드시 불리언인 것은 아니에요. 원래 피연산자 중 하나를 반환해요(논리 연산자에 관한 MDN 문서 참고).

    null || 'hello';
    // => 'hello'
    

문자열 문맥

덧셈 연산자 +를 원시 값에 사용하는데 피연산자 하나가 문자열이면, 다른 하나도 문자열로 강제 변환돼요. 변환 논리는 String 함수를 사용할 때와 같아요. 그다음 두 문자열이 이어 붙여져요.

let name;
'hello ' + name;
// => 'hello undefined'

문자열이 아닌 값이 템플릿 문자열에 들어 있을 때도 같은 암시적 변환이 일어나요.

const degrees = 23;
`It is ${degrees} °C`;
// => 'Is is 23 °C.';

숫자 문맥

많은 연산자가 위에서 설명한 Number 함수의 논리에 따라 (필요하다면) 피연산자를 숫자로 강제 변환해요.

  • 산술 연산자: +(문자열이 포함되지 않은 경우), -, *, /, %, **
  • 단항 플러스 및 단항 부정 연산자: +, -
  • 관계 연산자(문자열이 아닌 피연산자의 경우): >, >=, <, <=
  • 비트 연산자: |, &, ^, ~

이 연산자들에 대한 더 자세한 내용은 MDN 연산자 목록을 참고해요.

피연산자가 문자열일 가능성이 있다면, 실수를 피하기 위해 항상 Number 함수로 명시적으로 변환하는 게 가장 좋아요.

'1' + '2';
// => '12'
// addition operator in string context as explained above

Number('1') + Number('2');
// => 3

가끔 단항 플러스 연산자로 문자열을 숫자로 강제 변환하는 코드를 보게 될 거예요. 이 방법은 명시적인 Number 호출보다 읽기 훨씬 어렵기 때문에 권장하지 않아요.

const value = '42';
+value;
// => 42

Number(value);
// => 42

느슨한 동등 및 부등 연산자 ==/!=를 사용할 때도 숫자로의 암시적 변환이 자주 일어나요. 하지만 이 연산자들의 정확한 논리는 꽤 복잡해요(느슨한 동등성에 관한 MDN 문서 참고). 결과를 예측하기 어렵고, 때로는 예상과 다른 값이 나와요. 이런 암시적 변환을 피하려면 엄격한 동등/부등 연산자 ===/!==를 사용해요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요

타입 변환 배우기