[모던 자바스크립트 Deep Dive]09장 타입 변환과 단축 평가
9.1 타입 변환이란?
- 명시적 타입 변환(explicit coercion) 또는 타입 캐스팅(type casting)
- 개발자가 의도적으로 값의 타입을 변환
- 암묵적 타입 변환(implicit coercion) 또는 강제 변환(type coercion)
- 개발자의 의도와는 상관 없이 표현식을 평가하는 중 자바스크립트가 암묵적으로 타입을 변환
- 타입 변환은 기존 원시 값을 직접 변경하지 않는다.
- 원시 값은 변경 불가능한 값(immutable value)이다.
9.2 암묵적 타입 변환
9.2.1 문자열 타입으로 변환
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 숫자 타입
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] }"
- 자바스크립트 엔진은 문자열 연결 연산자의 피연산자 중 문자열 타입이 아닌 것을 문자열 타입으로 암묵적 타입 변환
- 리터럴의 표현식 삽입은 평가 결과를 문자열 타입으로 암묵적 타입 변환
9.2.2 숫자 타입으로 변환
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 문자열 타입
+"" + // -> 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 2 3 4 5
1 - "1"; // -> 0 1 * "10"; // -> 10 1 / "one"; // -> NaN "1" > 0; // -> true
- 숫자 타입으로 변환할 수 없는 경우 평가 결과는
NaN
- 숫자 타입으로 변환할 수 없는 경우 평가 결과는
9.2.3 불리언 타입으로 변환
- 자바스크립트 엔진은 조건식의 평가 결과를 Truthy 값 또는 Falsy 값으로 구분하여 암묵적 타입 변환
- Falsy 값
false
undefined
null
0
,-0
NaN
‘’
- Truthy 값
{}
,[]
를 포함하여 그냥 Falsy 값 외의 모든 값
9.3 명시적 타입 변환
- 표준 빌트인 생성자 함수
- 자바스크립트에서 기본 제공
- 객체를 생성하기 위한 함수
new
연산자와 함께 호출
- 표준 빌트인 메서드
- 자바스크립트에서 기본 제공
- 빌트인 객체의 메서드
9.3.1 문자열 타입으로 변환
String
생성자 함수를new
연산자 없이 호출하는 방법1 2 3 4 5 6 7
// 숫자 타입 => 문자열 타입 String(1); // -> "1" String(NaN); // -> "NaN" String(Infinity); // -> "Infinity" // 불리언 타입 => 문자열 타입 String(true); // -> "true" String(false); // -> "false"
Object.prototype.toString
메서드를 이용하는 방법1 2 3 4 5 6 7
// 숫자 타입 => 문자열 타입 (1).toString(); // -> "1" NaN.toString(); // -> "NaN" Infinity.toString(); // -> "Infinity" // 불리언 타입 => 문자열 타입 true.toString(); // -> "true" false.toString(); // -> "false"
문자열 연결 연산자를 이용하는 방법
1 2 3 4 5 6 7
// 숫자 타입 => 문자열 타입 1 + ""; // -> "1" NaN + ""; // -> "NaN" Infinity + ""; // -> "Infinity" // 불리언 타입 => 문자열 타입 true + ""; // -> "true" false + ""; // -> "false"
9.3.2 숫자 타입으로 변환
Number
생성자 함수를new
연산자 없이 호출하는 방법1 2 3 4 5 6 7
// 문자열 타입 => 숫자 타입 Number("0"); // -> 0 Number("-1"); // -> -1 Number("10.53"); // -> 10.53 // 불리언 타입 => 숫자 타입 Number(true); // -> 1 Number(false); // -> 0
parseInt
,parseFloat
함수를 사용하는 방법- 문자열만 가능
1 2 3 4
// 문자열 타입 => 숫자 타입 parseInt("0"); // -> 0 parseInt("-1"); // -> -1 parseFloat("10.53"); // -> 10.53
+
단항 산술 연산자를 이용하는 방법1 2 3 4 5 6 7
// 문자열 타입 => 숫자 타입 +"0"; // -> 0 +"-1"; // -> -1 +"10.53"; // -> 10.53 // 불리언 타입 => 숫자 타입 +true; // -> 1 +false; // -> 0
*
산술 연산자를 이용하는 방법1 2 3 4 5 6 7
// 문자열 타입 => 숫자 타입 "0" * 1; // -> 0 "-1" * 1; // -> -1 "10.53" * 1; // -> 10.53 // 불리언 타입 => 숫자 타입 true * 1; // -> 1 false * 1; // -> 0
9.3.3 불리언 타입으로 변환
Boolean
생성자 함수를new
연산자 없이 호출하는 방법1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 문자열 타입 => 불리언 타입 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
!
부정 논리 연산자를 두 번 사용하는 방법1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 문자열 타입 => 불리언 타입 !!"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 논리 연산자를 이용한 단축 평가
표현식을 평가하는 도중 평가 결과가 확정된 경우 나머지 평가 과정 생략
단축 평가 표현식 평가 결과 true | | anything
true
false | | anything
anything
true && anything
anything
false && anything
false
논리곱(&&
) 연산자와 논리합(||
) 연산자
- 좌항에서 우항으로 평가 진행
- 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환
- 단축 평가 진행
논리곱 연산자는 조건이 Truthy 값일때 수행하는
if
문을 대체할 수 있고, 논리곱은 조건이 Falsy 값일때 수행하는if
문을 대체할 수 있다.1 2 3 4 5 6 7 8 9 10
var done = true; var message = ""; // 주어진 조건이 true일 때 if (done) message = "완료"; // if 문은 단축 평가로 대체 가능하다. // done이 true라면 message에 '완료'를 할당 message = done && "완료"; console.log(message); // 완료
1 2 3 4 5 6 7 8 9 10
var done = false; var message = ""; // 주어진 조건이 false일 때 if (!done) message = "미완료"; // if 문은 단축 평가로 대체 가능하다. // done이 false라면 message에 '미완료'를 할당 message = done || "미완료"; console.log(message); // 미완료
단축 평가의 유용한 패턴
객체의 프로퍼티 참조시
TypeError
를 피할 때- 변수가 객체의 프로퍼티를 가리키려 하지만 사실
null
이나undefined
를 가리키고 있다면 에러가 발생한다. 단축평가를 사용하여 이를 피할 수 있다.
1 2
var elem = null; var value = elem.value; // TypeError: Cannot read property 'value' of null
1 2 3 4
var elem = null; // elem이 null이나 undefined와 같은 Falsy 값이면 elem으로 평가되고 // elem이 Truthy 값이면 elem.value로 평가된다. var value = elem && elem.value; // -> null
- 변수가 객체의 프로퍼티를 가리키려 하지만 사실
함수 매개변수에 기본값을 설정할 때
- 함수 호출시 인수를 전달하지 않으면 매개변수에
undefined
가 할당된다. 단축평가를 이용해 이를 원하는 기본값으로 설정할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 단축 평가를 사용한 매개변수의 기본값 설정 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
- 함수 호출시 인수를 전달하지 않으면 매개변수에
9.4.2 옵셔널 체이닝 연산자
1
2
3
4
5
6
var elem = null;
// elem이 null 또는 undefined이면 undefined를 반환하고,
// 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
var value = elem?.value;
console.log(value); // undefined
- ES11에서 도입
- 좌항의 피연산자가
null
또는undefined
인 경우undefined
를 반환하고 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
객체 프로퍼티 참조시 논리곱 연산자와의 차이
논리곱 연산자는 좌항 피연산자가 Falsy 값이면 좌항 피연산자를 그대로 반환
1 2 3 4 5 6 7
var str = ""; // 문자열의 길이(length)를 참조한다. var length = str && str.length; // 문자열의 길이(length)를 참조하지 못한다. console.log(length); // ''
옵셔널 체이닝 연산자는 좌항 피연산자가
null
또는undefined
인 경우만 아니라면 계속 우항의 프로퍼티를 참조1 2 3 4 5 6 7
var str = ""; // 문자열의 길이(length)를 참조한다. // 이때 좌항 피연산자가 false로 평가되는 Falsy 값이라도 // null 또는 undefined가 아니면 우항의 프로퍼티 참조를 이어간다. var length = str?.length; console.log(length); // 0
9.4.3 null 병합 연산자
1
2
3
4
// 좌항의 피연산자가 null 또는 undefined이면 우항의 피연산자를 반환하고,
// 그렇지 않으면 좌항의 피연산자를 반환한다.
var foo = null ?? "default string";
console.log(foo); // "default string"
- ES11에서 도입
- 좌항의 피연산자가
null
또는undefined
인 경우 우항의 피연산자를 반환하고 그렇지 않으면 좌항의 피연산자를 반환한다.
변수 기본값 설정시 논리합 연산자와의 차이
- 논리합 연산자는 좌항 피연산자가 Falsy 값이면 우항 피연산자를 그대로 반환
1 2 3
// Falsy 값인 0이나 ''도 기본값으로서 유효하다면 예기치 않은 동작이 발생할 수 있다. var foo = "" || "default string"; console.log(foo); // "default string"
- null 병합 연산자는 좌항 피연산자가
null
또는undefined
인 경우만 아니라면 좌항 피연산자를 그대로 반환1 2 3 4
// 좌항의 피연산자가 Falsy 값이라도 // null 또는 undefined이 아니면 좌항의 피연산자를 반환한다. var foo = "" ?? "default string"; console.log(foo); // ""
This post is licensed under CC BY 4.0 by the author.