[JS] DeepDive - 9장

Baoro·2022년 6월 26일
0

DeepDive

목록 보기
7/9
post-thumbnail

타입 변환과 단축 평가

타입 변환이란 무엇인가?

자바스립트에는 모든 값에 타입이 있다. 숫자, 문자, boolean ...
이런 타입들이 개발자의 의도나 의도와는 상관없이 변환되는 것을 타입 변환이라고 한다.


1. 암묵적 타입 변환

개발자와의 의도와는 상관없이 표현식을 평가하는 도중에 암묵적으로 타입이 자동 변환되는 것을 말한다.

var x = 10;
var str = x + '';	

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

두번째 콘솔로그에서 볼 수 있듯이 암묵적으로 생성된 '10'은 x에 재할당 되지는 않는다. 한번 쓰고 버리는 것이다. 이러한 암묵적인 타입 변환은 개발자의 의도와는 다르게 자동으로 변환이 되기 때문에 오류를 생산할 가능성을 높인다.
그렇다면 암묵적 타입은 무조건 사용하지 말아야할까?
꼭 그렇지만은 않다. 암묵적 타입은 가독성 측면에서 더 좋을 수 있다.
예를 들면 (10).toString()보다 10+''가 더 간결해지기 때문이다.
중요한 것은 개발자로서 코드를 정확히 예측할 수 있어야한다는 것이다.

이게 왜 이런 결과값이 나오는지, 어떤 식으로 작성해야 간결하면서 동료가 더 쉽게 이해할 수 있어야하는지 알 수 있어야 한다.

1-1. 문자열 타입으로 변환 ( + )

1 + '2'	// "12"

+연산자는 피연산자가 숫자일 때는 우리가 아는 더하기 역할을 하지만 피연산자가 문자일 때는 문자열을 연결해주는 문자열 연결 연산자로 동작한다.
하지만 위 예제처럼 피연산자가 문자와 숫자가 되있다면 어떻게 될까? 이럴 때는 숫자 타입이 암묵적으로 문자타입으로 변경된다. 즉 숫자 1은 '1'이 된다.

// 숫자 타입
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

1-2. 숫자 타입으로 변환 ( - * / )

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

위 예제에서 사용한 연산자 -, *, / 는 모두 산술 연산자이다. 즉 피연산자가 모두 산술이여야하는데 자바스크립트 엔진은 숫자 타입이 아닌 피연산자를 암묵적으로 숫자 타입으로 변환시킨다.

// 문자열 타입
+''       // -> 0
+'0'      // -> 0
+'1'      // -> 1
+'string' // -> NaN

// 불리언 타입
+true     // -> 1
+false    // -> 0

// null 타입
+null     // -> 0

// undefined 타입
+undefined // -> NaN

// 심벌 타입
+Symbol() // -> ypeError: Cannot convert a Symbol value to a number

// 객체 타입
+{}             // -> NaN
+[]             // -> 0
+[10, 20]       // -> NaN
+(function(){}) // -> NaN

1-3. 불리언 타입으로 변환

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

자바스크립트에서 if문이나 for문, 삼항 조건 연산자는 불리언 값이 필요하다.
이러한 불리언 값도 암묵적으로 변환시킬 수 있다.
true나 false가 아닌 값을 어떻게 변환시킬까?
자바스크립트 엔진은 Truthy값 또는 Falsy값으로 구분한다.
Truthy값은 Falsy값을 제외한 모든 값이다. 그래서 Falsy값만 외우면 된다.

  • False
  • undefined
  • null
  • 0, -0
  • NaN
  • ''(빈 문자열)

따라서 위 예제의 결과값은 2, 4이다.


2. 명시적 타입 변환

개발자 의도에 따라 명시적으로 변경하는 것을 말한다.

2-1. 문자열 타입으로 변환

문자열 타입이 아닌 타입을 문자열 타입으로 변환하는 방법 3가지

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

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

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

2-2. 숫자 타입으로 변환

숫자 타입이 아닌 타입을 숫자 타입으로 변환하는 방법 4가지

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

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

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

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

2-3. 불리언 타입으로 변환

불리언 타입이 아닌 값을 불리언 타입으로 변환하는 2가지 방법

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

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

3. 단축 평가

3-1. 논리 연산자

'Cat' && 'Dog'	// "Dog"
'Cat' || 'Dog'	// "Cat"

논리곱 연산자는 두 개의 피연산자가 모두 true로 평가될 때 true를 반환한다.
첫번째 값이 Truthy값이지만 두번째 값을 평가해야지 위 표현식을 평가할 수 있다.
즉 두번째 피연산자가 논리곱 연산자 표현식의 평가 결과를 결정한다.
즉 'Dog'를 반환한다.

논리합 연산자는 두 개의 피연산자 중 하나만 true로 평가되어도 true를 반환한다.
첫번째 피연산자 'Cat'이 Truthy 값이므로 true로 평가된다.

논리곱 연산자와 논리합 연산자는 이처럼 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략한다.

3-2. 옵셔널 체이닝 연산자

var elem = null
var value = elem?.value;
console.log(value);		// undefined

옵셔널 체이닝 연산자 ?.는 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
위 예제의 경우 elem이 null 이기 때문에 undefined를 반환한다.

var elem = null
var value = elem && elem.value;
console.log(value);		// null

옵셔널 체이닝 연산자가 없었을 때는 위 예제와 같이 논리 연산자 &&를 이용하여 변수가 null 또는 undefined인지 확인했다.
elem이 Falsy값이면 elem으로 평가되고, Truthy값이면 elem.value로 평가된다. 하지만 좌항 피연산자가 Falsy값인 0이나 ''은 객체로 평가될 때도 있다.

var str = '';
var length = str && str.length;
console.log(length);	// ''

str이 공백인 경우 0을 반환해야하지만 위 예제의 경우 ''을 반환한다.
즉 문자열의 길이를 참조하지 못한다. 이럴경우 옵셔널 체이닝을 이용한다.

var str = '';
var length = str?.length;
console.log(length);	// 0

좌항 피연산자가 Falsy 값이더라도 null이나 undefined가 아니면 우항의 프로퍼티를 참조한다.

3-3. null 병합 연산자

null 병합 연산자 ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.

var foo = null ?? 'default string';
console.log(foo);	// "default string"

null 병합연산자는 변수에 기본값을 설정할 때 유용하다. null 병합연산자가 없을 때는 논리연산자 ||를 사용하여 기본값을 설정했다.

var foo = '' || 'default string';
console.log(foo);	// "default string"

하지만 예제와 값이 기본값을 ''로 설정하고 싶지만 좌항 피연산자 값이 Falsy한 값인 ''이나 0인 경우 의도하지 않은 동작을 발생시킨다.

var foo = '' ?? 'default string';
console.log(foo);	// ""

하지만 null 병합연산자를 이용하면 좌항 피연산자가 Falsy값이라고 해도 null 또는 undefined가 아니면 좌항의 피연산자를 그대로 반환하기 때문에 기본값을 설정할 떄는 논리연산자를 이용하는 것보다 null 병합 연산자를 이용하는 것이 더 좋다

profile
꾸준히.... 깔끔하게.... 끝까지....

0개의 댓글