명시적 타입 변환 ( 타입 캐스팅 ) : 개발자가 의도적으로 타입을 변환하는 것이다.
암묵적 타입 변환 ( 타입 강제 변환, type conversion) : 자바스크립트 엔진에 의해 실행 도중에 타입이 변환되는 것을 말한다.
한 가지 명심해야 할 것은 명시적 타입 변환이나 암죽적 타입 변환이나 기존 원시 값을 직접 변경하는 것은 아니다.
원시 값은 immutable한 값이기 때문에 변경이 불가능하다. 단지, 다른 타입의 새로운 값을 생성하는 것이다.
var temp = 1;
console.log(typeof temp.toString()); // string
console.log(typeof temp) // Number
위는 명시적인 타입 변환에 해당한다. 그러나, temp 변수의 타입은 아직 Number이다. 즉 타입 변환을 한다고해서 기존의 변수 타입이 바뀌는 것이 아니고 다른 타입에 같은 값을 새로 만드는 것이다.
암죽적 타입 변환 역시도 마찬가지이다. 새로 만든 값을 할당하지 않는 이상 암묵적 변환으로 타입이 변환되진 않는다.
var x = 10;
var str = x + '';
console.log(typeof str) // string
console.log(typeof x) // number
str에 x + '' 을 넣을 때 x의 값인 10은 '10'으로 암묵적으로 변환된다. 그러나, x의 값이 바뀌는 것은 아니다.
피연산자 + 피연산자로 연결할 때 피연산자 중에 하나라도 문자열이라면 문자열로 변환된다.
참고로 문자열 + 문자열은 문자열문자열 이라는 것을 명심하도록 하자
1 + '2' // 12
산술 연산자인 + 말고 -, *, / 모두 숫자가 아닌 피연산자를 바꾸어 연산을 할 수 있다. 그러나 연산이 불가능한 경우에는 Nan이 나온다.
1 - '1'; // 0
1 * '10'; // 10
1 / 'one'; // NaN
만약 피연산자가 하나 뿐인 단항 연산자 + 을 사용한다면 피연산자를 숫자로 바꿀 수 있다.
var x = '10';
x = +x;
console.log(typeof(x)); // number
이 역시도 숫자로 변환이 안되는 값이라면 NaN이 된다.
이는 저번 포스트의 falsy, truly를 생각하면 된다.
다시 정리하자면 다음의 falsy를 제외한 나머지는 truly이다.
3가지 방법이 있는데 다음과 같다.
console.log(String(10)); // 1번의 경우
console.log((10).toString()); // 2번의 경우
console.log(10 +''); // 3번의 경우
숫자타입이 아닌 값을 숫자 타입으로 변환하는 방법은 다음과 같다.
console.log(Number('10'))
console.log(parseInt('10'))
console.log(parseFloat('10'))
console.log(+'10')
console.log(1*'10')
console.log(Boolean(''))
console.log(Boolean(0))
console.log(!!1)
부정 논리 연산자를 사용해도 되지만 명시적으로 좋지 않으므로 가독성을 위해 생성자를 이용해서 사용하는 방법이 제일 좋은 방법이라고 생각한다.
단축 평가( short-circuit evaluation )은 평가 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다.
first && second
first || second
조건문을 평가할 때 AND(&&)는 앞부분이 true이면 뒤가 false이냐, true이냐에 따라 결과가 결정된다. 만약 앞부분이 false이면 뒷부분은 필요없으므로 앞 부분의 값만으로 결과만으로 평가된다.
따라서 다음의 결과가 가능하다.
var temp = 'CAT' && 'DOG'
console.log(temp) // DOG
앞이 truly이기 때문에 뒷부분이 결과를 결정하게 된다. 따라서 뒷부분의 값이 변수에 할당된다.
var temp = 'CAT' || 'DOG'
console.log(temp) // CAT
OR연산은 앞부분만으로 결정이 되기 때문에 평가 결과가 앞이 나온다. 따라서 앞의 'CAT'이 변수에 할당되는 것이다.
정리하면 다음과 같다.
true || anything ----> true
false || anything ----> anything
true && anything ----> anything
false && anything ----> false
이를 이용하여 다음의 방법을 사용할 수 있다.
var elem = null;
var value = elem && elem.value; // null
js의 경우 object가 null 또는 undefined 인 경우에 propery 접근을 시도한 경우 TypeError가 발생한다. 이러면 프로그램이 강제 종료된다.
따라서 이를 체크하기 위해 위의 테크닉을 사용할 수 있다.
elem이 null이기 대문에 false가 나온다. 따라서 and 연산의 경우 단축 평가 때문에 false가 value에 할당되고 뒤는 실행되지 않는다.
반대로 elem에 object가 할당된 경우 elem은 true가 되므로 뒤의 값이 변수에 할당되어 뒤의 elem.value가 할당 된다.
물론 타입스크립트를 사용하면 쉽게 해결된다~!
뭔가 말이 어려워 보이는데, kotlin을 사용해본 경험자들은 알만한 연산자이다.
즉, null을 체크하기위해 ?을 사용하는 문법으로 ?앞의 피연산자가 null이나 undefined이면 undefined를 주고 아니면 체이닝을 이어간다.
var elem = null;
var value = elem?.value;
console.log(value) // undefined
옵셔널 체이닝 연산자 ?. 을 사용하여 객체가 null, undefined인지 아닌지를 체크하는 것이다. 즉, kotlin에서 ? 을 사용하여 null 체크를 할 수 있도록 한 것과 마찬가지이다.
옵셔널 체이닝 연산자 ?. 를 사용한다면 위의 단축 평가(AND 연산자))를 사용하지 않고도 객체가 null / undefined인지를 평가할 수 있다는 장점이 있다.
옵셔널 체이닝 연산자가 단축 평가의 && 연산을 대체할 수 있다면 null 병합 연산자 ??은 or연산을 대체할 수 있다.
null 병합 연산자는 앞이 null, undefined라면 뒤를 반환하고, 앞이 null, undefined라면 뒤를 반환한다.
var foo = '' || 'default string';
console.log(foo) // 'default string'
or 단축 연산자를 사용하면 앞이 false이면 뒤를 반환한다. 따라서 다음과 같이 빈 문자열이 올 경우 false로 판단해버려서 빈 문자열을 넣어주지 못하는 경우가 있다. 이 때 null 병합 연산자를 사용하면 된다.
앞이 null 또는 undefined일 때만 뒤를 반환하고 싶을 때는 null 병합 연산자를 사용하면 된다.
var foo = '' ?? 'default string';
console.log(foo); // ''