1. 타입 변환이란?
1-1. 명시적 타입 변환
개발자가 의도적으로 값의 타입을 변환
- 타입 캐스팅 이라고도 칭함
var x = 77;
var str = x.toString(); // 의도적으로 number인 x를 String으로 타입 변환
console.log(typeof str, str); // string, '77'
1-2. 암묵적 타입 변환
개발자의 의도와는 상관없이 표현식을 평가하는 도중에 암묵적으로 타입이 자동 변환
- 타입 강제 변환 이라고도 칭함
var x = 77;
var str = 'My score is ' + x; // x는 number지만 String으로 자동 타입 변환
console.log(str);
1-3. 타입 변환의 특징
기존의 원시 값을 직접 변경하는 것이 아님
→ 기존 원시 값을 사용해 다른 타입의 새로운 원시 값을 생성하는 것
var grade = 1;
var str = 'My grade is ' + grade; // grade 는 String으로 암묵적 타입 변환
console.log(typeof grade);
// number
// 그러나 String으로 변환된 채로 재할당이 이루어지지는 않음
1-4. 명시적 and 암묵적
명시적 타입 변환과 달리 암묵적 타입 변환은 개발자의 의도가 코드에 명백히 나타나지 않는다. 따라서 개발자가 작성한 코드게 어떻게 암묵적 타입 변환이 일어나는지는 예측을 할 수 있어야 한다. 만약 결과를 예측하지 못하거나 예측에 실패한다면 오류가 발생할 가능성이 높아진다.
그렇다고 암묵적 타입 변환의 사용을 줄여야 하는 것은 아니다. 경우에 따라서는 암묵적 타입 변환이 코드의 가독성을 더 높일 수도 있다. 결국 중요한 것은 코드를 예측할 수 있어야 하고 자신의 코드를 다른 사람이 보더라도 쉽게 이해할 수 있도록 가독성을 높여야 한다.
2. 암묵적 타입 변환
실제로는 에러가 발생하는 코드라도 자바스크립트는 가급적 에러의 발생을 줄이기 위해 암묵적 타입 변환을 통해 표현식을 평가
2-1. 문자열 타입으로의 변환
var res = 'My score is ' + (7*11);
console.log(res);
위의 예제에서 ‘+’ 연산자는 문자열 연결 연산자로 작동하게 된다. 그러나 뒤의 (7*11) 피연산자의 경우 평가 결과 문자열이 아니기 때문에 암묵적 타입 변환에 의해 ‘77’ 로 타입 변환이 일어나게 된다.
2-1-1. 다양한 동작
// 숫자 -> 문자열
console.log(-0 + ''); // '0'
console.log(-1 + ''); // '-1'
console.log(-Infinity + ''); // '-Infinity'
// 불리언 -> 문자열
console.log(true + ''); // 'true'
console.log(false + ''); // 'false'
// null, undefined -> 문자열
console.log(null + ''); // 'null'
console.log(undefined + '') // 'undefined'
// symbol -> 문자열
console.log(Symbol() + '') // 타입 에러 : 변환 불가
// 객체 타입
console.log(Math + ''); // '[object Math]'
console.log([77,777] + ''); // '77, 777'
2-2. 숫자 타입으로의 변환
2-2-1. 산술 연산자
var score = 7 * '11';
console.log(score); // 77
위의 예제에서 ‘*’ 연산자는 곱셈 산술 연산자로 작동하게 된다. 그러나 뒤의 ‘11’ 피연산자의 경우 평가 결과 숫자 타입이 아니기 때문에 암묵적 타입 변환에 의해 77 로 타입 변환이 일어나게 된다.
이때, 피연산자를 숫자 타입으로 변환할 수 없는 경우에는 산술 연산이 불가능 하기에 평가 결과로 NaN 을 출력하게 된다.
2-2-2. 비교 연산자
console.log('100' > 77); // true
위는 비교 연산자를 이용한 예시이다. 비교 연산자는 피연산자들의 크기를 비교하기 때문에 해당 예시에서는 모두 숫자 타입이어야 한다. 결국 ‘100’은 100 으로 암묵적 타입 변환된다.
2-2-3. 단항 연산자
// 문자열 -> 숫자
console.log(+''); // 0
console.log(+'str'); // NaN
// 불리언 -> 숫자
console.log(+true); // 1
// null, undefined -> 숫자
console.log(+null); // 0
console.log(+undefined); // NaN
// symbol -> 숫자
console.log(+Symbol()); // 타입 에러 : 변환 불가
// 객체 -> 숫자
console.log(+{}); // NaN
console.log(+[]); // 0
console.log(+[77, 777]); // NaN
객체와 빈 배열이 아닌 배열, undefined 는 변환되지 않아 NaN 이 된다는 것을 주의하자.
2-3. 불리언 타입으로의 변환
불리언 타입이 아닌 값을 Truthy 값 또는 Falsy 값으로 구분된다. 즉, 제어문의 조건식과 같이 불리언 값으로 평가되어야 할 문맥에서 암묵적 타입 변환이 일어난다.
- Truthy 값
- 참으로 평가되는 값으로 true 로 변환
- Falsy 값
- 거짓으로 평가되는 값으로 false 로 변환
2-3-1. Falsy 로 평가되는 값
- false
- undefined
- null
- 0, -0
- NaN
- 비어있는 문자열
if(!NaN) console.log(NaN + ' is falsy value');
// 위의 경우 NaN 은 Falsy 로 평가되며 결국 !false 가 되어 true 가 된다.
💡 Truthy 로 평가되는 값의 경우 Falsy 로 평가되는 값 이외 모든 값은 모두 해당한다.
3. 명시적 타입 변환
표준 빌트인 생성자 함수를 new 연산자 없이 호출하는 방법과 빌트인 메서드를 사용하는 방법, 그리고 앞에서 살펴본 암묵적 타입 변환을 이용하는 방법이 존재
3-1. 문자열 타입으로의 변환
3가지의 방법으로 변환이 가능하며 그 중 하나인 문자열 연결 연산자를 이용한 방법은 암묵적 타입 변환에서와 똑같이 작동하기에 제외한 2가지를 알아보겠다.
3-1-1. String 생성자 함수를 new 연산자 없이 호출
console.log(String(NaN)); // 'NaN'
console.log(String(true)); // 'true'
console.log(String(undefined)); // 'undefined'
console.log(String(Math)); // '[object Math]'
3-1-2. Object.prototype.toString 메서드 사용
console.log((NaN).toString()); // 'NaN'
console.log((true).toString()); // 'true'
console.log((Math).toString()); // '[object Math]'
3-2. 숫자 타입으로의 변환
4가지의 방법으로 변환이 가능하며 그 중 ‘+’ 단항 산술 연산자와 산술 연산자를 이용한 방법은 암묵적 타입 변환에서와 똑같이 작동하기에 제외한 2가지를 알아보겠다.
3-2-1. Number 생성자 함수를 new 연산자 없이 호출
console.log(Number(null)); // 0
console.log(Number(true)); // 1
console.log(Number('77.77')); // 77.77
3-2-2. parseInt, parseFloat 함수를 사용하는 방법
console.log(parseInt('77')); // 77
console.log(parseFloat('77.77')); // 77.77
이 방법에서 주의할 점은 문자열만이 숫자 타입으로 변환이 가능하다는 것이다.
3-3. 불리언 타입으로의 변환
2가지의 방법으로 변환이 가능하다.
3-3-1. Boolean 생성자 함수를 new 연산자 없이 호출
console.log(Boolean('')); // false
console.log(Boolean('false')); // true
console.log(Boolean(undefined)); // false
console.log(Boolean([])); // true
3-3-2. ! 부정 논리 연산자를 두 번 사용하는 방법
console.log(!!''); // false
console.log(!!'false'); // true
console.log(!!undefined); // false
console.log(!![]); // true
4. 단축 평가
논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환
단축 평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략
4-1. 논리 연산자를 사용한 단축 평가
||(논리합) 또는 &&(논리곱) 연산자 표현식의 평가 결과는 불리언 값이 아닐 수도 있다. 따라서 언제나 2개의 피연산자 중 어느 한쪽으로 평가된다.
4-1-1. 논리합 연산자 ||
- 피연산자들 중 어느 하나라도 true 라면 결과가 true 로 평가
- 모두 false 라면 결과가 false 로 평가
- 좌항에서 우항으로 평가 진행
console.log('Pizza' || 'Chicken'); // 'Pizza'
// 'Pizza' 피연산자의 평가 결과는 Truthy 값으로 true
// 결국 뒤의 'Chicken' 은 평가할 필요도 없이 바로 'Pizza' 를 출력
4-1-2. 논리곱 연산자 &&
- 피연산자들 중 어느 하나라도 false 라면 결과가 false 로 평가
- 모두 true 라면 결과가 true 로 평가
- 좌항에서 우항으로 평가 진행
console.log('Pizza' && 'Chicken'); // 'Chicken'
// 'Pizza' 피연산자의 평가 결과는 Truthy 값으로 true
// 아직 표현식의 결과가 나오지 않았으니 계속 평가 진행
// 'Chicken' 피연산자의 평가 결과는 Truthy 값으로 true
// 표현식이 true 라는 평가 결과나옴 -> 'Chicken' 출력
4-2. 단축 평가의 규칙
단축 평가 표현식평가 결과
true || anything | true |
false || anything | anything |
true && anything | anything |
false && anything | false |
4-2-1. if 문의 대체
논리곱 연산자 && 는 어떤 조건이 Truthy 값일 때 수행해야하는 if 문을 대체 가능
var res = true;
var score;
if(res) score = 100;
// && 연산자를 이용한 대체
score = res && 100;
// res 가 true 라면 규칙에 따라 100 이 평가의 결과로 score 변수에 할당
console.log(score);
논리합 연산자 || 는 어떤 조건이 Falsy 값일 때 수행해야하는 if 문을 대체 가능
var res = false;
var score;
if(!res) score = 0;
// || 연산자를 이용한 대체
score = res || 0;
// res 가 false 라면 규칙에 따라 0 이 평가의 결과로 score 변수에 할당
console.log(score);
이외에도 객체나 함수에서도 유용하게 쓰일 수 있는 패턴이 있으나 아직 학습하지 않았기에 후에 다시 해당 부분을 학습할 때 다시 보겠다.
4-3. 옵셔널 체이닝 연산자 ?.
좌항의 피연산자가 null 또는 undefined 인 경우 undefined 를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다. 즉, 좌항의 피연산자가 Falsy 값이더라도 null 또는 undefined 가 아니면 우항의 프로퍼티 참조를 이어간다.
var str = '';
var length = str && str.length;
console.log(length); // ''
위의 경우에서 && 연산자를 사용했고 좌항의 str 변수가 Falsy 값이기에 단축 평가의 규칙에 의해 표현식이 false 로 평가되며 length 에는 str 의 값인 ‘’ 이 할당된다.
var str = '';
var length = str?.length;
console.log(length); // 0
그러나 옵셔널 체이닝 연산자를 사용하면 str 이 Falsy 값이지만 null 또는 undefined 가 아니기에 우항의 프로퍼티 참조를 계속 이어가게되어 length 변수에는 0이 할당된다.
4-4. null 병합 연산자 ??
좌항의 피연산자가 null 또는 undefined 인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.
var score2 = 0 ?? 'defeat';
console.log(score2); // 77
?? 연산자는 변수에 기본값을 설정할 때 유용하다. || 연산자의 경우 좌항의 피연산자가 Falsy 값이면 우항의 피연산자를 반환하지만 0 이나 ‘’ 도 기본값으로 유효하는 경우에는 원하는 결과를 얻을 수 없다. 이럴 때에 ?? 연산자를 사용하면 원하는 결과를 얻을 수 있게 된다.