자바스크립트 - 타입 변환

이정인·2022년 3월 3일
0

기초부터 완성까지, 프런트엔드를 읽고 정리한 내용입니다.

자바스크립트 타입 변환

자바스크립트에는 명시적 강제 변환암시적 강제 변환 두 가지의 타입 변환이 존재하는데 명시적 강제 변환은 의도적인 타입 변환을 나타내는 것이고, 암시적 강제 변환은 표현식의 평가 중 타입이 변환되는 것이다.

명시적 강제 변환

의도를 가지고 타입을 변환 하는 것

  • 문자열로 변환

    • String() 호출

      ECMAScript의ToString 추상 연산을 기준으로 이뤄진다. 객체의 경우 원시 타입으로 변환한 뒤 다시 한번 ToString 추상 연산을 수행한 값을 반환한다.

      Symbol은 문자열 숫자로 변환될 경우 TypeError가 발생하는데 객체의 다른 프로퍼티에 접근하는 것을 방지 하지 위해서이다.

    • toString() 메서드 이용

    둘의 차이점은 nullundefined 타입에서 나타난다.

    console.log(String(null)) // 'null'
    console.log(String(undefined)) // 'undefined'
    
    undefined.toString(); // TypeError 발생
    null.toString(); // TypeError 발생

    nullundefined 타입은 값이 비어 있음, 할당되지 않은 상태를 나타내는 원시 타입이므로 toString() 메서드를 호출할 수 없다. 객체가 아니기 때문에 객체에서 사용할 수 있는 프로퍼티들을 사용할 수 없다. 반면에 String()함수는 정의된 규칙에 따르기 때문에 문자열로 명시적 강제 변환이 가능하다.

  • 숫자로 변환

    • Number()

      ECMAScript의 ToNumber 추상 연산 명세를 기준으로 반환된다.

      BigInt, Symbol은 typeError 가 발생한다. BigInt는 큰 정수의 연산을 위해 나온 타입이기 때문에 숫자와 타입이 구분되어야 하기 때문이다.

    • parseInt()함수

      문자열만 대상으로 변환한다. 문자열이 아닌 경우에는 해당 값을 문자열로 변환한 후에 사용한다. 두 번째 인자는 기수를 의미한다. (10일 경우 10진수로 변환) 생략할 경우 첫번째 인자를 기준으로 추정하여 변환하므로 의도 하지 않은 결과가 나올 수도 있다.

      console.log(parseInt('10',10)) // 10

      Number()는 숫자로 변경 불가능한 문자가 있으면 싸가지 없이 바로 NaN을 반환 하지만, parseInt는 최대한 숫자로 변환하여 결과를 반환한다.

      console.log(Number('10A', 10)); // NaN
      console.log(parseInt('10A', 10)); //10
  • 불리언으로 변환

    ECMAScript의 ToBoolean 추상 연산 명세를 기준으로 반환된다.

    falsy 값의 기준 또한 위의 명세를 따른 것이다.

    Boolean()함수를 호출하는 방법과 부정 연산자를 사용하는 방법이 있으며 둘 다 동일한 결과를 반환한다.

객체의 원시 타입 변환

객체의 원시 타입 변환은 문자열로 변환, 숫자로 변환 두 가지로 나눌 수 있으며 valueOf(), toString() 이 쓰인다. ECMAScript에서는 ToPrimitive 추상 연산으로 정의 하고 있다.

  • 문자열로 변환

    • 객체에 정의된 toString()을 호출한다. 없으면 prototype.toString() 메서드를 실행한다. Object.prototype.toString() 는 결과값으로 '[Object object]' 문자열을 반환한다.
    • 1단계가 원시 타입이라면 그 결과를 문자열로 반환하고, 아니면 valueOf()메서드를 호출한다. 없다면 Object.prototype.valueOf()을 실행한다.
    • valueOf() 메서드의 결과 값이 원시 타입이라면 그 결과를 문자열로 변환하여 반환하고, 그렇지 않다면 TypeError가 발생한다.
    console.log(String({})) // '[Object object]'
  • 숫자로 변환

    • 객체에 정의된 valueOf()메서드를 호출한다. 없다면 Object.prototype.valueOf()을 실행한다. Object.prototype.valueOf()메서드는 결과값으로 객체를 그대로 반환한다.
    • 1단계의 결과가 원시타입이라면 그 결과를 숫자로 변환하여 반환하고, 그렇지 않다면 toString()을 호출한다. 없으면 기본적으로 prototype.toString() 메서드를 실행한다.
    • toString()의 결과가 원시 타입이라면 그 결과를 숫자로 변환하여 반환하고 그렇지 않다면 TypeError가 발생한다.
    console.log(Number({})); // NaN

배열, Date 정규식과 같은 특수한 객체들은 자체적인 toString() 또는 valueOf() 메서드를 가지고 있다.

암시적 강제 변환

암시적 강제 변환은 연산 중에 내부적으로 타입을 변환하는 것이다. 이 또한 ECMAScript 명세의 기준대로 정확하게 동작하고 있다.

  • 덧셈 연산자

    • 피연산자 중 하나가 문자열 타입인 경우 나머지 타입도 문자열로 변환하여 병합한다.

      console.log(1 + ''); // '1'
    • 피연산자 중 하나가 객체이며 문자열로 변환 가능한 경우 문자열로 변환하여 연산한다.

      console.log(1 + {}); // '1[object Object]'
    • 피연산자가 모두 문자열, 객체가 아니면 숫자로 변환하여 연산한다. 만약 변환 결과 타입이 다르면 TypeError가 발생한다.

      console.log(1 + true); //2
  • 동등 연산자

    동등 연산자의 가장 큰 특징은 암시적 강제 변환을 허용하는 것이다. 피연산자 타입이 서로 같은 경우에는 변환하지 않는다.

    • 피연산자 중 하나는 문자열, 하나는 숫자인 경우 문자열을 숫자로 변환하여 동등함을 비교한다.

      console.log(1 == '1'); // true
    • 문자열, BigInt => 문자열을 Bigint로 변환하여 비교

    • null == undefined 인경우 동등

    • 피연산자 중 하나가 불리언이면 불리언을 숫자로 변환하여 동등함 비교

      console.log(ture == 1) ; // true
    • 객체 == (문자열, 숫자, BigInt, symbol) 일 경우 객체를 원시타입으로 비교하여 동등함을 비교

      console.log('[object Object]' == {}); // true
    • 숫자 == BigInt 인 경우 내부적인 숫자 비교 알고리즘에 따라 비교한 결과를 반환

    가독성이 떨어지는 경우가 생길 수 있다.

    console.log(true == '1'); //true
  • 비교 연산자

    • 문자열 비교

      각 문자를 알파벳 순서로 비교한다.

      console.log('1' < '04') // false

      왼쪽부터 '1'과 '0'을 비교하고 그 다음 문자를 비교한다.

      객체인 경우 원시타입으로 변환한 후에 비교한다.

      console.log(['a'] < ['b']) // true
    • 문자열 외

      • 하나는 문자열 다른 하나는 bigInt인 경우 문자열을 bigInt로 변환하고 비교
      • 피연산자를 모두 숫자로 변환하여 비교한다. 숫자와 BigInt는 숫자 알고리즘에 의해 비교

    다른 타입 간의 비교 연산에서 암시적인 강제 변환을 막을 수 없다.

  • 조건 표현식

    모든 값은 불리언으로 변환되어 조건 표현식에서 평가된다.

    const a = 0;
    const b = 'javscript';
    const c = null
    
    if (a) {
    	console.log('falsy');
    }
    
    while (b) {
     console.log('truthy');
     break;
    }
    
    console.log(c ? 'truthy' : 'falsy'); // 'falsy'
    
  • 논리 연산자

    자바스크립트 논리 연산자의 특이한 점은 논리 연산자의 값이 불리언 타입이 아닐 수 있다는 것이다.

    • && 논리 연산자는 첫 번째 피연산자와 값이 true로 평가되는 경우 두 번째 피연산자의 값을 반환하고, false가 되면 첫 번째 피연산자의 값을 반환한다.
    • || 논리 연산자는 첫 번째 피연산자의 값이 true로 평가되는 경우 첫 번째 피연산자의 값을 반환하고, false로 평가되면 두 번째 피연산자의 값을 반환한다.
    const a = null;
    const b = 'javascript';
    const c = 1;
    
    console.log(a && b) ; //null
    console.log(b || c) ; //'javascript'

    디폴트 값을 설정하거나 조건에 따라 함수를 실행할 때 유용하다. 리액트에서 컴포넌트를 조건에 따라 렌더링할 때 자주 사용한다. 만약 falsy 값이 아닌 null, undefined처럼 값이 비어 있는 경우에만 디폴트 값을 설정하고 싶을 때는 ES2020에서 등장한 null 병합을 사용할 수 있다.

    const a = ''
    const b = a ?? 'default';

0개의 댓글