null과 undefined 그리고 NaN
대부분의 프로그래밍 언어는 null 이라는 특별한 값을 지원한다.
ex> var temp = null;
이 값(null)의 의미는 '아무런 값도 나타내지 않는다'라는 의미이며 다음의 구문과는 구분된다.
ex> var temp;
즉, null 은 어떠한 유효한 값도 아니라는 의미이지 값 자체가 없다는 의미가 아니라는 말이다. 다시 말해 변수 temp에는 어떤 유효한 데이터를 담지 않을 뿐, null 값을 가진다는 의미이다. 따라서 선언만 하고 값을 할당하지 두 번재 예와는 구분되는 것이다.
자바스크립트는 값의 비유효성과 관련한 또 하나의 의미를 제공하는데 바로 undefined이다.
앞서 두 번째 예가 바로 undefined의 예가 되겠다. 즉 선언은 되었지만 값이 할당되지 않는 변수에 접근할 경우 undefined가 된다.
console.log(temp); //선언은 되었으나 값이 할당되지 않은 변수: undefined
temp = null;
console.log(temp); //여전히 유효한 값은 없으나 null로 할당된 변수: null
결론적으로 null은 null이라는 값이 할당된 경우이지만, undefined의 경우 선언은 되었지만 아무런 값도 할당되지 않은 경우로 요약할 수 있다.
좀 더 나아가 객체 환경에서의 undefined를 살펴볼 필요가 있다.
선언은 되었지만 값이 할당되지 않은 변수에 접근할 경우 undefined라 했다. 이 개념은 객체환경에서도 동일한다. 즉 선언은 되었지만 값이 할당되지 않는 객체 프로퍼티 역시 undefined이다.
여기에 한가지 더 기억해야 할 것은, 객체 환경에서는 선언되지 않는 객체 프로퍼티도 undefined라는 점이다.
일반 변수의 경우 선언되지 않은 경우 오류(Exception)을 내뱉지만 객체 프로퍼티일 경우에는 오류가 아니라 undefined라는 점이다.
this.i;
}
var tempObject = new TempObject();
console.log(tempObject.i); //선언은 되었으나 값이 할당되지 않은 객체 프로퍼티: undefined
console.log(tempObject.j); //존재하지 않는 객체 프로퍼티 역시...: undefined
문맥에 따른 null, undefined 평가
자바스크립트는 유연한 자동 형변환이 지원되는 언어이다. 자동 형변환이란 어떤 데이터 타입이 숫자와 함께 사용될 경우 자동으로 (원래 숫자 타입이 아닌 경우에도) 자동으로 정해진 숫자로 변환되는 것이다.
여기서 숫자와 함께 사용된 경우라는 의미가 바로 프로그램 문맥상 숫자 문맥으로 평가된다는 것이다.
null과 undefined 역시 문맥에 따른 자동 형변환이 된다.
Boolean 문맥
null과 undefined는 실제로 다른 값이지만 참/거짓(Boolean)으로 평가되어야 하는 경우 모두 false로 형변환이 된다.
console.log(Boolean(temp)); //강제 형변환: false
if(!temp) //자동 현변환: undefined가 자동으로 false로 변환됨
{
console.log('temp 변수가 false로 평가되었습니다');
}
숫자 문백
숫자 문맥에서는 두 값이 차이를 보이는데 null의 경우 0으로, undefined의 경우 NaN으로 변환된다.
var temp2;
console.log(Number(temp1)); //강제 형변환: 0
console.log(Number(temp2)); //강제 형변환: NaN
console.log(temp1 + 2); //자동형변환: 2
console.log(temp2 + 2); //자동형변환: NaN
실제로 자바스크립트 모듈을 개발할 경우, 이러한 문맥상 자동형변환의 특징을 이용하는 경우가 많다.
만일 어떤 객체에 정의된 함수의 존재여부를 식별한 후 해당 함수를 호출하고 싶을 경우 다음과 같이 작성할 수 있다.
this.doWork = function(){
console.log('doWork...');
}
}
var temp = new TempObject();
if(temp.doWork){
temp.doWork(); //조건식이 true이므로 호출됨
}
if(temp.doWork2){
temp.doWork2(); //조건식이 false이므로 호출되지 않음
}
그리고 외부 모듈을 가져다 쓰는 복잡한 스크립트 환경에서 전역 네임스페이스의 충돌을 방지하기 위한 조건식으로 사용되기도 한다.
다음의 경우를 살펴보자. 동일한 이름의 객체를 생성하면 오류는 나지 않지만 뒤에 선언된 이름이 앞선 이름을 덮어쓰게 된다.
console.log(someName.i); //10
var someName = { i : 20 };
console.log(someName.i); //20
문제는 만일 someName이라는 심벌이 외부 모듈에서 전역 네임스페이스로 이미 사용중일 경우 이름 중복은 예상치 못한 결과를 초래하기 때문에 다음과 같이 전역 네임스페이스에 동일한 심벌이 존재하는지 여부를 판단하는 것이 좋다.
console.log(someName.i); //10
if(!someName){ //만일 someName이라는 심벌이 정의되지 않았다면 새로 정의한다.
var someName = { i : 20 };
}
console.log(someName.i); //10
물론 이름 충돌 방지는 도메인 네임과 같은 고유성이 보장된 이름 규칙을 사용하고 나아가 익명함수로 전역 네임스페이스를 전혀 어지럽히지 않도록 하는 기법이 존재하지만 여기서는 그 평가로 사용되는 undefined 특징을 살펴본 것이다.
참고로 null과 undefined의 문맥에 따른 자동 형변환 표를 정리한다.
|
Boolean 문맥 |
숫자 문맥 |
문자열 문맥 |
null |
false |
0 |
"null" |
undefined |
false |
NaN |
"undefined" |