오늘은 모던 자바스크립트의
타입 변환 항목에 대해서 포스팅하려고 한다.
자바스크립트의 모든 값은 타입이 존재한다.
타입은 개발자의 의도대로 변할 수 있는경우와 그렇지 않은 경우가 있다.
이를 명시적 타입변환 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 값이다
이 외의 값들은 모두 true로 평가되는 Truthy값이다.
개발자의 의도로 명시적으로 타입을 변경하는 것이다.
// 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 연산자 없이 호출하는 방법
// 문자열 타입 => 숫자 타입
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
// 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)라 부른다. 단축 평가는 아래의 규칙을 따른다.
단축평가는 아래와 같은 상황에서 유용하게 사용된다.
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