모던 자바스크립트 Deep Dive (5)

Daon·2023년 3월 24일
0

모던자바스크립트

목록 보기
5/12
post-thumbnail

오늘은 모던 자바스크립트의
타입 변환 항목에 대해서 포스팅하려고 한다.

_타입 변환이란?

자바스크립트의 모든 값은 타입이 존재한다.
타입은 개발자의 의도대로 변할 수 있는경우와 그렇지 않은 경우가 있다.
이를 명시적 타입변환 or 타입 캐스팅 그리고 암묵적 타입 변환 or 타입 강제변환 이라고 한다.

var x = 10;

// 명시적 타입 변환
var str = x.toString(); // 숫자를 문자열로 타입 캐스팅한다.
console.log(typeof str); // string

var c = 10;

// 암묵적 타입 변환
// 숫자 타입 x의 값을 바탕으로 새로운 문자열 타입의 값을 생성해 표현식을 평가한다.
var str = c + '';

console.log(typeof str, str); // string 10

명시적 타입변환과 암묵적 타입변환 둘 다 기존의 값을 변경하는것은 아니다.
변수 값을 재할당해서 변경하는 것이 아니라 엔진에서 표현식을 에러없이 평가하기 위해
기존 값을 바탕으로 새로운 타입의 값을 만들어서 단 한 번 사용하고 버린다.

위 예제의 경우, 자바스크립트 엔진은 표현식 x + ‘‘을 평가하기 위해 변수 x의 숫자 값을 바탕으로 새로운 문자열 값 ‘10’을 생성하고 이것으로 표현식 ‘10’ + ‘‘를 평가한다. 이때 자동 생성된 문자열 ‘10’은 표현식의 평가가 끝나면 아무도 참조하지 않으므로 가비지 컬렉터에 의해 메모리에서 제거된다.

암묵적 타입 변환

자바스크립트 엔진은 표현식을 평가 할 때 문맥, 즉 컨텍스트에 고려하여 암묵적 타입 변환을 실행한다.

// 표현식이 모두 문자열 타입이여야 하는 컨텍스트
'10' + 2               // '102'
`1 * 10 = ${ 1 * 10 }` // "1 * 10 = 10"

// 표현식이 모두 숫자 타입이여야 하는 컨텍스트
5 * '10' // 50

// 표현식이 불리언 타입이여야 하는 컨텍스트
!0 // true
if (1) { }

문자열 타입으로 변환

1 + '2' // "12"
  • 연산자는 피연산자 중 하나 이상이 문자열이면 문자열 연결 연산자로 사용된다.
    그러므로 문자열 연결 연산자의 피연산자는 문맥상 '문자열'이여만 한다.
// 숫자 타입
0 + ''              // "0"
-0 + ''             // "0"
1 + ''              // "1"
-1 + ''             // "-1"
NaN + ''            // "NaN"
Infinity + ''       // "Infinity"
-Infinity + ''      // "-Infinity"
// 불리언 타입
true + ''           // "true"
false + ''          // "false"
// null 타입
null + ''           // "null"
// undefined 타입
undefined + ''      // "undefined"
// 심볼 타입
(Symbol()) + ''     // TypeError: Cannot convert a Symbol value to a string
// 객체 타입
({}) + ''           // "[object Object]"
Math + ''           // "[object Math]"
[] + ''             // ""
[10, 20] + ''       // "10,20"
(function(){}) + '' // "function(){}"
Array + ''          // "function Array() { [native code] }"

숫자 타입으로 변환

1 - '1'    // 0
1 * '10'   // 10
1 / 'one'  // NaN

위에 연산자는 모두 산술 연산자이다.
숫자를 결과로 출력하는 것이 산술 연산자이다. 그렇기에 피연산자는 문맥 상 숫자 타입이여야 한다.
만약 숫자로 변환할 수 없는 경우 NaN을 반환한다.
그 외의 다른 경우는

'1' > 0   // true

비교 연산자이다. 이는 피연산자의 크기를 비교하므로 문맥 상 숫자 타입이여야한다.
+단항 연산자는 피연산자의 숫자 타입이 값이면 숫자 타입의 값으로 암묵적 타입 변환을 한다.

// 문자열 타입
+''             // 0
+'0'            // 0
+'1'            // 1
+'string'       // NaN
// 불리언 타입
+true           // 1
+false          // 0
// null 타입
+null           // 0
// undefined 타입
+undefined      // NaN
// 심볼 타입
+Symbol()       // TypeError: Cannot convert a Symbol value to a number
// 객체 타입
+{}             // NaN
+[]             // 0
+[10, 20]       // NaN
+(function(){}) // NaN

불리언 타입으로 변환

if ('') console.log(x);

보통 if문이나 for문에서 변환이 이루어 진다.

if ('')    console.log('1');
if (true)  console.log('2');
if (0)     console.log('3');
if ('str') console.log('4');
if (null)  console.log('5');

// 2 4

이 때 자바스크립트 엔진은 불리언 타입이 아닌 값을
Truthy 값(참으로 인식할 값) 또는 Falsy 값(거짓으로 인식할 값)으로 구분한다. 즉, Truthy 값은 true로, Falsy 값은 false로 변환된다.

아래는 false로 평가되는 Falsy 값이다

  • false
  • undefined
  • null
  • 0, -0
  • NaN
  • "(빈문자열)"

이 외의 값들은 모두 true로 평가되는 Truthy값이다.

명시적 타입 변환

개발자의 의도로 명시적으로 타입을 변경하는 것이다.

문자열 타입으로 변환

  1. String 생성자 함수를 new 연산자 없이 호출하는 방법
  2. Object.prototype.toString 메소드를 사용하는 방법
  3. 문자열 연결 연산자를 이용하는 방법
// 1. String 생성자 함수를 new 연산자 없이 호출하는 방법
// 숫자 타입 => 문자열 타입
console.log(String(1));        // "1"
console.log(String(NaN));      // "NaN"
console.log(String(Infinity)); // "Infinity"
// 불리언 타입 => 문자열 타입
console.log(String(true));     // "true"
console.log(String(false));    // "false"

// 2. Object.prototype.toString 메소드를 사용하는 방법
// 숫자 타입 => 문자열 타입
console.log((1).toString());        // "1"
console.log((NaN).toString());      // "NaN"
console.log((Infinity).toString()); // "Infinity"
// 불리언 타입 => 문자열 타입
console.log((true).toString());     // "true"
console.log((false).toString());    // "false"

// 3. 문자열 연결 연산자를 이용하는 방법
// 숫자 타입 => 문자열 타입
console.log(1 + '');        // "1"
console.log(NaN + '');      // "NaN"
console.log(Infinity + ''); // "Infinity"
// 불리언 타입 => 문자열 타입
console.log(true + '');     // "true"
console.log(false + '');    // "false"

숫자 타입으로 변환

  1. Number 생성자 함수를 new 연산자 없이 호출하는 방법
  2. parseInt, parseFloat 함수를 사용하는 방법(문자열만 변환 가능)
  3. 단항 연결 연산자를 이용하는 방법
  4. 산술 연산자를 이용하는 방법
// 1. Number 생성자 함수를 new 연산자 없이 호출하는 방법
// 문자열 타입 => 숫자 타입
console.log(Number('0'));     // 0
console.log(Number('-1'));    // -1
console.log(Number('10.53')); // 10.53
// 불리언 타입 => 숫자 타입
console.log(Number(true));    // 1
console.log(Number(false));   // 0

// 2. parseInt, parseFloat 함수를 사용하는 방법(문자열만 변환 가능)
// 문자열 타입 => 숫자 타입
console.log(parseInt('0'));       // 0
console.log(parseInt('-1'));      // -1
console.log(parseFloat('10.53')); // 10.53

// 3. + 단항 연결 연산자를 이용하는 방법
// 문자열 타입 => 숫자 타입
console.log(+'0');     // 0
console.log(+'-1');    // -1
console.log(+'10.53'); // 10.53
// 불리언 타입 => 숫자 타입
console.log(+true);    // 1
console.log(+false);   // 0

// 4. * 산술 연산자를 이용하는 방법
// 문자열 타입 => 숫자 타입
console.log('0' * 1);     // 0
console.log('-1' * 1);    // -1
console.log('10.53' * 1); // 10.53
// 불리언 타입 => 숫자 타입
console.log(true * 1);    // 1
console.log(false * 1);   // 0

불리언 타입으로 변환

  • Boolean 생성자 함수를 new 연산자 없이 호출하는 방법
  • !부정 논리 연산자를 두번 사용하는 방법
// 1. Boolean 생성자 함수를 new 연산자 없이 호출하는 방법
// 문자열 타입 => 불리언 타입
console.log(Boolean('x'));       // true
console.log(Boolean(''));        // false
console.log(Boolean('false'));   // true
// 숫자 타입 => 불리언 타입
console.log(Boolean(0));         // false
console.log(Boolean(1));         // true
console.log(Boolean(NaN));       // false
console.log(Boolean(Infinity));  // true
// null 타입 => 불리언 타입
console.log(Boolean(null));      // false
// undefined 타입 => 불리언 타 입
console.log(Boolean(undefined)); // false
// 객체 타입 => 불리언 타입
console.log(Boolean({}));        // true
console.log(Boolean([]));        // true

// 2. ! 부정 논리 연산자를 두번 사용하는 방법
// 문자열 타입 => 불리언 타입
console.log(!!'x');       // true
console.log(!!'');        // false
console.log(!!'false');   // true
// 숫자 타입 => 불리언 타입
console.log(!!0);         // false
console.log(!!1);         // true
console.log(!!NaN);       // false
console.log(!!Infinity);  // true
// null 타입 => 불리언 타입
console.log(!!null);      // false
// undefined 타입 => 불리언 타입
console.log(!!undefined); // false
// 객체 타입 => 불리언 타입
console.log(!!{});        // true
console.log(!![]);        // true

단축 평가

'Cat' && 'Dog' // “Dog”

논리 곱 연산자 (&&)는 두개의 피연산자가 모두 true 일 때 true를 반환한다
논리곱 연산자 &&는 논리 연산의 결과를 결정한 두번째 피연산자의 평가 결과 즉, 문자열 ‘Dog’를 그대로 반환한다.

'Cat' || 'Dog' // 'Cat'

논리 곱 연산자 (||)는 두개의 피연산자 중 하나만 true 일 때 true를 반환한다.
논리합 연산자 ||는 논리 연산의 결과를 결정한 첫번째 피연산자의 평가 결과 즉, 문자열 ‘Cat’를 그대로 반환한다.

논리곱 연산자 &&와 논리합 연산자 ||는 이와 같이 논리 평가를 결정한 피연산자의 평가 결과를 그대로 반환한다. 이를 단축 평가(Short-Circuit evaluation)라 부른다. 단축 평가는 아래의 규칙을 따른다.

단축평가는 아래와 같은 상황에서 유용하게 사용된다.

객체가 null인지 확인하고 프로퍼티 참조

var elem = null;

console.log(elem.value); // TypeError: Cannot read property 'value' of null
console.log(elem && elem.value); // null

함수의 인수를 초기화 할 때

// 단축 평가를 사용한 매개변수의 기본값 설정
function getStringLength(str) {
  str = str || '';
  return str.length;
}

getStringLength();     // 0
getStringLength('hi'); // 2

// ES6의 매개변수의 기본값 설정
function getStringLength(str = '') {
  return str.length;
}

getStringLength();     // 0
getStringLength('hi'); // 2

참조
https://poiemaweb.com/js-type-coercion

profile
같이 일하고싶은 그런 개발자!

0개의 댓글