특이한 typeof
typeof
연산자는 피연산자의 타입을 문자열 형태로 리턴하는 연산자이며 여러가지 특이한 부분이 있다.
typeof null; // object
typeof undefined; // undefined
typeof function(){} // function
typeof [] // object
제일 특이한 부분이 null
값의 타입이 object
라는 것이며 이는 falsy 한 값이기 때문에 다음과 같이 확인하는 것이 정확하다.
var a = null;
(!a && typeof a === 'object'); // true
선언되지 않은 것 vs 정의되지 않은 것
Undeclared(선언되지 않은 것)과 undefined(정의되지 않은 것)는 완전히 다른 개념이다. Undeclared의 경우는 아예 변수 자체가 선언되지 않음을 뜻하며 undefined는 변수에 값이 할당되지 않은 것을 말한다.
var a;
a; // undefined
b; // ReferenceError: b가 정의되지 않았습니다.
따라서 위와 같이 사용할 경우 에러가 발생한다.
typeof 안전가드(Safety Guard)
방금 위에서 본 차이점을 통해서 undeclared 변수를 사용하려고 할 경우에 에러가 발생한다는 것을 알 수 있다. 하지만 typeof
연산자를 사용한다면 모두 undefined
값이 나온다.
var a;
typeof a; // undefined
typeof b; // undefined
따라서 이 특성을 적극 활용하면 다음과 같은 경우에 유용하다.
- 전역 네임스페이스를 공유하고 있고 특정한 전역변수가 존재하는지 확인할 때
- 사용하는 유틸리티 파일에 특정 변수가 존재하는지 확인할 때
function doSomething() {
var helper = (typeof FeatureXYZ !== 'undefined') ? FeatureXYZ : function() {}
.....
}
위와 같이 안전가드를 사용할 수 있다.
유사배열을 배열로 바꾸자!
Array.prototype.slice
사용 (ES6 이전)
function test() {
var arr = Array.prototype.slice.call(arguments);
console.log(arr);
}
test(1,2,3); // [1, 2, 3]
Array.from
사용 (ES6)
function test() {
var arr = Array.from(arguments);
console.log(arr);
}
test(1,2,3); // [1, 2, 3]
문자열과 배열은 다르다.
문자열은 유사배열이며 불변 값이지만 배열은 가변값이다. 따라서 배열에서 유용한 가변배열 메서드는 불변 값인 문자열에서 사용할 수 없다. 하지만 배열에서도 불변배열 메서드가 있기 때문에 그걸 문자열에 빌려쓸 수 있는 형태이다.
var a = 'foo';
var b = Array.prototype.join.call(a, '-'); // 'f-o-o'
var c = Array.prototype.map.call(a, function(aa) {
return aa.toUpperCase() + '.';
}).join(''); // 'F.O.O.'
불변배열 메서드인 join
과 map
은 문자열에 쓸 수 있는 걸 볼 수 있다.
배열에는 가변배열 메서드인 reverse
가 있는데 이는 역시 가변배열 메서드이기 때문에 문자열에 사용할 수 없다. 따라서 야매스러운 방법을 사용한다.
var a = '123';
var c = a.split('').reverse().join(''); // '321';
문자열을 배열르 분할한 후에 역으로 나열하고 그걸 합치는 방법이다. 이는 단순 문자열에 굉장히 효과적이지만 유니코드 문자가 섞여 있는 경우는 불가하니 유니코드의 경우를 사용하고 싶다면 Esrever 를 참고하자.
숫자 소수점 이하 조정하기
var a = 77.89;
a.toFixed(0); // 77
a.toPrecision(2); // 77
기능은 비슷하지만 toFixed
의 경우 소수점 이하의 개수를 지정하고 toPrecision
의 경우는 유효숫자의 개수를 지정한다.
undefined와 null
undefined와 null 모두가 primitive type인데 특징이 다르다.
- undefined
- 식별자(identifier)로 사용될 수 있다.
- 값이 비어있는 상태를 표현한다. 즉, 선언은 되었지만 할당되지 않은 상태이다.
- null
- 식별자로 사용될 수 없다.
- “값 아닌 값”을 표현한다. 즉, 값이 아닌것을 표현하는 값이다.
NaN, 무한대, 0
NaN(Not a Number)
NaN은 “숫자 아님”이라는 뜻의 값으로 경계값(Sentinal Value)의 일종이다. 숫자 집합에서 특정한 종류의 에러 상황을 나타내기 때문에
typeof
연산자를 적용하면number
를 리턴한다.전역객체인
window
가isNaN()
이라는 판단함수를 가지고 있지만 이는 “숫자 아님”을 판단하고 NaN에 대해선 엄밀히 판단하지 못한다. 따라서 ES6에 도입된Number.isNaN()
을 사용해야 한다.NaN은 자기 자신과도 동등하지 않은 유일한 값 으로 반사성(Reflexivity)이 없다.
var a = 'NaN' / 3; // NaN a === a; // false
무한대
var a = 1 / 0; // Infinity == Number.POSITIVE_INFINITY var b = 1 / -0; // Infinity == Number.NEGATIVE_INFINITY var c = a / b; // NaN
0
-0
도 있다는 것을 알아두자.
var a = 0 / 3; // 0
var b = 0 / -3; // -0
여기서도 이상한 현상이 있는데 문자열 '-0'
을 -0
으로 변환시킬 때는 잘 되지만 그 역은 0
으로만 나온다.
var a = '-0';
var b = -0;
Number(a); // -0
b.toString(); // '0'
비교를 할 때도 0
과 -0
은 ==
를 쓰든지 ===
를 쓰든지 같다고 도출되기 때문에 ES6에서 도입된 Object.is()
를 사용하도록 하자. 이 부분은 NaN의 비교에도 마찬가지이다.