[모던 자바스크립트 Deep Dive] 9장 타입 변환과 단축 평가

jini.choi·2023년 10월 24일
0
post-thumbnail

9.1 타입 변환이란?

  • 자바스크립트의 모든 값은 타입이 있다.

  • 개발자가 의도적으로 값의 타입을 변환하는 것을 아래와 같이 부른다.

    • 명시적 타입 변환(explicit coercion) 또는
    • 타입 캐스팅 (type casting)
  • 개발자 의도와는 상관없이 표현식 평가 도중 자바스크립트 엔진에 의해 암묵적으로 타입이 자동으로 변환되는 것은 아래와 같이 부른다.

    • 암묵적 타입 변환(implicit coercion) 또는
    • 타입 강제 변환(type coercion)
var x = 10;

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

// 암묵적 타입 변환
// 문자열 연결 연산자는 숫자 타입 x의 값을 바탕으로 새로운 문자열을 생성한다.
var str2 = x + '';
  • 명시적, 암묵적 타입 변환 모두 기존 원시 값(위에서 x변수의 값)을 직접 변경하는 것이 아니다. 원시값은 변경 불가능한 값(immutable value)이므로 변경할 수 없다.

9.2 암묵적 타입 변환

  • 자바스크립트 엔진은 표현식을 평가할 때 개발자의 의도와는 상관없이 코드의 문맥을 고려해 암묵적으로 데이터 타입을 강제 변환

9.2.1 문자열 타입으로 변환

1 + '2' // "12"
  • +연산자는 하나 이상이 문자열이므로 문자열 연결 연산자로 동작한다.

  • 문자열 연결 연산자의 모든 피연산자는 코드의 문맥상 모두 문자열 타입이여야 한다.

  • 템플릿 리터럴의 표현식 삽입은 표현식의 평가 결과를 문자열 타입으로 암묵적 타입 변환한다.

`1 + 1 = ${1 + 1}` //"1 + 1 = 2"
  • 자바스크립트 엔진은 문자열 연산자 표현식을 평가하기 위해 문자열 연결 연산자의 피연산자 중에서 문자열 타입이 아닌 피연산자를 문자열 타입으로 암묵적 타입 변환한다.
// 숫자 타입
0 + ''			// "0"
-0 + ''			// "0"
1 + ''			// "1"
-1 + ''			// "-1"
NaN + ''		// "NaN"
Infinity + ''	// "Infinity"

// 불리언 타입
true + ''		// "true"

// 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] }"

9.2.2 숫자 타입으로 변환

✅ 산술 연산자

  • +산술 연산자를 제외하고 다른 모든 산술 연산자는 숫자타입이 아닌 피연산자를 숫자타입으로 암묵적 타입 변환한다.

  • 숫자 타입으로 변환이 불가능한 경우 NaN를 반환한다.

1 - '1'		// 0
1 * '10'	// 10
1 / 'one'	// 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

9.2.3 불리언 타입으로 변환

  • 제어문 또는 삼항 조건 연산자의 조건식은 불리언 값으로 평가되어야하기 때문에 자바스크립트 엔진은 조건식의 평가 결과를 불리언 타입으로 암묵적 타입 변환한다.
  • 불리언 타입이 아닌 값을 Truthy값 또는 Falsy값으로 구분한다.

  • Falsy값(그 외는 모두 Truthy값)

false
undefined
null
0, -0
NaN
''(빈 문자열)
  • Truthy/Falsy값을 판별하는 함수
// 전달받은 인수가 Falsy 값이면 true 반환, Truthy 값이면 false를 반환한다.
function isFalsy(x) {
 	return !x;
}
// 전달받은 인수가 Truthy 값이면 true, Falsy 값이면 false를 반환한다.
function isTruthy(x) {
  	return !!x;
}

// 모두 true를 반환한다.
isFalsy(undefined);
isFalsy(null);
isFalsy(0);
  
// 모두 true를 반환한다.
isTruthy('0');	// 빈 문자열이 아닌 문자열은 Truthy 값이다.
isTruthy({});
isTruthy([]);

9.3 명시적 타입 변환

  • 개발자 의도에 따라 명시적으로 타입을 변경하는 방법은 다양하다.

    • 표준 빌트인 생성자 함수(String, Number, Boolean)를 new 연산자 없이 호출하는 방법

    • 빌트인 메서드 사용하는 방법

    • 암묵적 타입 변환을 이용하는 방법

    표준 빌트인 생성자 함수 : 객체를 생성하기 위한 함수. new 연산자와 함께 호출.
    표준 빌트인 메서드 : 자바스크립트에서 기본 제공하는 빌트인 객체 메서드(21장 확인)

9.3.1 문자열 타입으로 변환

문자열 타입이 나닌 값을 문자열 타입으로 변환하는 방법은 다음과 같다.

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"

9.3.2 숫자 타입으로 변환

숫자 타입이 아닌 값을 숫자 타입으로 변환하는 방법은 다음과 같다.

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

9.3.3 불리언 타입으로 변환

불리언 타입이 아닌 값을 불리언 타입으로 변환하는 방법은 다음과 같다.

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

9.4 단축 평가

9.4.1 논리 연산자를 사용한 단축 평가

💡 논리 연산자

'Cat' && 'Dog'	// "Dog"
  • 논리곱(&&)

    • 두개의 피연산자가 모두 true로 평가될 때 true를 반환한다.

    • 좌항에서 우항으로 평가를 진행한다.

    • 두개가 모두 true이면 두번째 피연산자가 반환된다.

'Cat' || 'Dog'	// "Cat"
  • 논리합(||)

    • 두개의 피연산자 중 하나만 true로 평가되어도 true를 반환한다.

    • 좌항에서 우항으로 평가가 진행된다.

    • 첫번째 피연산자가 true이면 두번째것을 평가하지 않기 때문에 "Cat"을 반환

💡 단축평가

  • 표현식을 평가하는 도퉁에 평가 결과가 확정된 경우 나머지 평가 과정을 생략한다.
  • 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환한다.
  • 단축평가 규칙
단축 평가 표현식평과 결과
true ¦¦ anythingtrue
false ¦¦ anythinganything
true && anythingtrue
false && anythingfalse
'cat' || 'dog'   // cat
false || 'dog'   // dog
'cat' || false   // cat

'cat' && 'dog'   // dog
false && 'dog'   // false
'cat' && false   // false

💡 단축평가 활용

객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때

  • elem이 null이나 undefined와 같은 Falsy 값이면 elem으로 평가되고
  • elem이 Truthy 값이면 elem.value로 평가된다.
var elem = null;
  
var value2 = elem && elem.value;	// null

함수 매개변수에 기본값을 설정할 때

  • 함수를 호출할 때 인수를 전달하지 않으면 매개변수에는 undefined가 할당된다.

  • 이때 단축평가를 사용해undefined로 인해 발생할 수 있는 에러를 방지할 수 있다.

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

// ES6의 매개변수의 기본값 설정으로도 해결 가능
function getStringLength2(str = ''){
  return str.length;
}

9.4.2 옵셔널 체이닝 연산자

  • ES11(ECMAScript2020)에서 도입됐다.
  • 옵셔널 체이닝 연산자 ?.좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티를 참조한다.
  • 옵셔널 체이닝이 도입되기 이전 논리 연산자 &&를 사용하여 null 또는 undefined인지 확인했지만 Falsy값 중 0이나 ''은 객체로 평가될 때도 있다.
var elem = null;

// elem이 null 또는 undefined이면 undefined를 반환, 그렇지 않으면 우항의 프로퍼티를 참조
var value = elem?.value;
console.log(value);        // undefined

9.4.3 null 병합 연산자

  • ES11(ECMAScript2020)에서 도입됐다.
  • null 병합 연산자 ??는 좌항의 피연산자가 null 또는 undefiend인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.
  • 변수의 기본값 설정할 때 유용
  • null 병합 연산자가 도입되기 이전엔 논리연산자 || 를 사용했었는데 마찬가지로 Falsy값 중 0이나 ''이 기본 값으로서 유효하다면(사용해야된다면) 예기치 않은 동작이 발행할 수 있다.
var foo = null ?? 'default string';
console.log(foo); // "default string"
profile
개발짜🏃‍♀️

0개의 댓글