📝

10. null과 undefined

 

10-1. null 과 undefined의 정의와 예시

10-1-1. null

null은 어떤 값이 의도적으로 비어있음을 표현하며 불리언 연산에서는 거짓으로 취급된다. 변수는 존재하나null로 (값이) 할당된 상태, 즉 null은 자료형이 정해진 상태이다. 또한 식별되지 않아 변수가 아무런 객체를 가리키지 않음을 표현한다. [1]
 
// 정의되지 않고 초기화된 적도 없는 a a; // ReferenceError: a is not defined // 존재하지만 값이나 자료형이 존재하지 않는 a var a = null; a; // null
 
함수가 유효한 값을 반환할 수 없는 경우, 명시적으로 null을 반환한다. 예를 들어 조건에 부합하는 HTML 요소를 검색해 반환하는 document.querySelector() 또는 getElementById()는 조건에 부합하는 HTML 요소를 검색할 수 없는 경우, null을 반환한다.
 
var garage = document.querySelector('.myCar'); console.log(garage); // null var garage = document.getElementById('#myCar'); console.log(garage); // null
 
또한 두 번째 매개변수로 배열을 전달하면 그 요소들을 차례대로 인수로 사용하는 apply 함수를 이용한 최댓값(Math.max)과 최솟값(Math.min)을 구하는 요소로도 쓰인다. 첫 번째 파라미터에 null을 넣어준 뒤 배열의 요소들을 입력하면 최댓값 혹은 최솟값이 나오게 된다.
 
Math.max.apply(null, [1, 2, 3]); // -> 3 Math.min.apply(null, [1, 2, 3]); // -> 1

10-1-2. undefined

undefined는 값이 없다는 것을 확인하는 값이다. 변수는 존재하나 어떠한 값도 할당받지 않아 자료형이 정해지지 않은 상태이다. 또한 메서드와 선언도 평가할 변수가 값을 할당받지 않은 경우에 undefined를 반환한다. 함수는 값을 명시적으로 반환하지 않으면 undefined를 반환한다.
 
var a; console.log(a); // undefined // 파라미터가 있는 함수를 호출 function a(x) { console.log(x); // undefined } a(); // undefined
 
예를 들어 파라미터가 있는 함수를 호출할 시, 값을 전달하지 않으면 함수 내에서 활용될 때 undefined 값이 된다. 이 케이스는 변수를 선언만 하고 값을 할당해 주지 않은 것과 동일한 케이스로 볼 수 있다.
 
const a = { lastName: 'Kim', }; console.log(a.lastName); // Kim console.log(a.firstName); // undefined
 
또한 자바스크립트는 오브젝트 내부에 존재하지 않는 프로퍼티(속성)를 참조할 시, 오류가 나타나는 것이 아닌 undefined 값을 반환한다. 그렇기 때문에 실수로 속성 이름을 잘못 입력할 경우에도 확인해 볼 수 있고 혹은 객체에 특정한 프로퍼티가 있는지, 속성 유무를 확인할 경우에도 볼 수 있다.

10-2. undefined와 null의 비교

간단하게 얘기하자면 undefined는 변수를 선언했지만 값을 아직 할당하지 않은 상태이고, null은 변수를 선언하고 ‘빈 값’이라는 값을 할당한 상태이다.

10-2-1. 공통점

  1. undefined와 null은 모두 ‘값이 없음’을 의미한다.
동등 연산자(==)는 두 값의 일치 여부를 느슨하게 검사한다. undefinednull의 경우에는 이 없음이라는 공통점에 초점을 맞추어 true를 반환하게 된다.
 
console.log(null == undefined) // true
 
느슨하게 검사하는 동등 연산자와는 다르게 일치 연산자(===)는 두 값의 일치 여부를 엄격하게 검사하기 때문에 false를 반환하게 된다.
console.log(null === undefined) // false
 
  1. falsy 값에 속한다.
undefinednull은 모두 falsy 값에 해당한다. 따라서 조건문이나 반복문 등 불리언 값이 필요한 상황에서 false로 처리가 된다.
 
if (undefined) { console.log('a'); } else { console.log('b'); } // 'b' if (null) { console.log('c'); } else { console.log('d'); } // 'd'
 
같은 의미에서 부정연산자를 사용했을 경우에는 true가 나온다.
 
console.log(!null) // true console.log(!undefined) // true
 
불리언 값으로 형 변환(Type Conversion)을 해주면 false가 나오는 것을 볼 수 있다.
 
console.log(!!null) // false console.log(!!undefined) // false
 
0처럼 nullundefined도 falsy 값이기 때문에 false와 동등 연산자(==)를 통해 비교했을 경우 true가 출력될 것이라고 생각할 수 있다.
 
console.log(null == false) // false console.log(null === false) // false console.log(null == true) // false console.log(null === true) // false console.log(undefined == false) // false console.log(undefined === false) // false console.log(undefined == true) // false console.log(undefined === true) // false
 
하지만 undefinednull은 동등 연산자(==)를 통해 비교를 했을 때, 서로와 자신에 대해서만 true가 출력 되고 그 외에는 어떤 값이 와도 false가 출력이 된다.
falsy값들에 대한 동등 비교(Equality comparisons)falsy값들에 대한 동등 비교(Equality comparisons)
falsy값들에 대한 동등 비교(Equality comparisons)

10-2-2. 차이점

  1. 값이 없는 이유가 다르다.
undefinednull은 크게 보았을 때, 값이 없음은 동일하지만 더 자세하게 들여다보면 차이가 있다. 우선, undefined는 변수를 선언하고 값을 아직 할당하지 않은 상태이다. 여기에는 빈 값이 들어갈 수도 있고 아니면 다른 값이 들어갈 수도 있다. 어떤 값이 들어갈지 모르겠는 상태를 의미한다.
반면에 null은 변수를 선언하고 빈 값을 할당한 상태이다. 이는 말 그대로, 여기의 값은 ‘비어있다’고 할당을 이미 한 것이다. 따라서 의도적으로 비어있는 값이 필요한 경우에는 null을 써주어야 한다.
 
  1. undefined는 암시적이고 null은 명시적이다.
undefined의 경우에는 변수를 선언하고 값을 할당하지 않으면 자바스크립트 엔진이 알아서 반환해 준다. 하지만, null의 경우에는 값이 없음을 사용자가 명시적으로 표현하기 위해서 사용한다. 의도적인 빈 값이 필요할 경우나 앞에 참조하던 값을 더 이상 참조하지 않을 경우에 사용한다.
 
let hello; console.log(hello); // undefined let bye = 3; bye = null; console.log(bye); // null

10-2-3. 간단한 비유를 통한 비교

undefinednull은 영화관 좌석에 비유할 수 있다. 아래의 그림처럼 영화가 시작하기 전에 비어있는 좌석 A와 좌석 B가 존재한다. 여기에서 Aundefined이고 Bnull이 된다. 일단 두 좌석은 크게 봤을 때 현재 ‘비어있다’는 공통점이 있다.
notion imagenotion image
하지만 자세하게 들여다보면, 비어있는 이유나 상황이 다르다.
A는 그냥 비어있는 좌석이다. 이 좌석에는 누군가 티켓을 사서 들어올 수도 있고 혹은 그냥 빈 채로 영화가 시작될 수 있는 ‘아무것도 정해지지 않은’ 빈 좌석이다. undefined라고 봤을 때 값이 아직 할당되지 않아 빈 값이 될 수도 있고, 혹은 다른 값이 할당될 수도 있는 상태인 것이다. 반면에 B는 의자의 고장 혹은 오염으로 사람이 앉을 수 없게 영화관 측에서 ‘X’라고 표시해놓고 비워둔 좌석이다. null이라고 봤을 때, 빈 값이라고 사용자가 할당한 상태인 것이다.

10-3. typeof 연산자

typeof 연산자는 자료형을 나타내는 문자열을 반환해 주는 연산자이다. 자료형의 종류에는 원시 타입과 객체 타입이 있다. 기본 원시형(Primitive Type)에는 number, string, boolean, null, undefined, symbol이 있다. 기본 원시형은 객체도 아니고 메서드도 가지지 않은 데이터를 말한다.
 
console.log(typeof true); // boolean console.log(typeof 24); // number console.log(typeof 'start'); // string
 
객체형에는 functionobject가 있다.
 
console.log(typeof [a,b,c]); // object console.log(typeof class name{}); // function
 
typeof 연산자를 통해 nullundefined의 자료형을 확인해 보면 각각 objectundefined가 나온다.
console.log(typeof null); // object console.log(typeof undefined); // undefined
 
여기서 이상한 점은 null 값이 object 즉 객체로 반환된다는 것이다. 이는 자바스크립트 첫 구현 시 생긴 버그인데, 초기 버전의 JavaScript는 32 bit 단위로 변수의 값이 저장되었다. 1-3비트에서는 타입 태그로 변수의 타입에 대해 저장했는데 그 중 객체가 000이었고 null은 Null pointer(대부분의 플랫폼에서 0x00로 표시)로 표시되었고 그 결과 null의 자료형이 object로 반환되었다.[2] 이는 초기 자바스크립트의 버그이기에 수정을 요청했으나 이미 ECMAScript에서 기존 코드에 영향을 미칠 수 있다며 거절되었다.
typeof null의 결과가 오류임을 인정하는 Javascript 설계자 브랜든 아이크typeof null의 결과가 오류임을 인정하는 Javascript 설계자 브랜든 아이크
typeof null의 결과가 오류임을 인정하는 Javascript 설계자 브랜든 아이크

10-4. null, undefined 와 비교 연산자

nullundefined는 일치 연산자가 아니라 동등 연산자를 통해 비교해야 true 값을 반환한다고 했다. 이 이유를 더 깊이 알기 위해서는 null, undefined를 대소 관계 비교 연산자를 통해 알아볼 필요가 있다. null0과 비교하면 논리에 맞지 않는 결과가 나온다.
 
null > 0 // false null == 0 // false null >= 0 // true
 
null이 0보다 크거나 같다고 했으면 위의 결과도 둘 중에 하나는 참으로 나와야 하나 둘 다 거짓을 반환한다. 이는 동등 연산자가 대소 관계 비교 연산자 <, > ,<=, >= 의 동작 방식과 다르기 때문이다. null >= 0true로 나오는 이유는 대소 관계 비교 연산자가 null을 숫자형 0으로 변환시키기 때문이다. undefined의 경우 비교 연산자에서는 NaN(숫자형)으로 변환된다. 대소 관계 비교 연산자는 NaN이 피연산자인 경우 false를 반환하게 된다.
 
undefined > 0 // flase undefined == 0 // flase undefined >= 0 // flase
 
+ null // 0 1 + null // 1 + undefined // NaN 1 + undefined // NaN
 
그래서 isNaN 연산자로 null을 검사할때 숫자 0으로 반환시켜 false가 뜨게 되는 것이다.
 
isNaN(null) // false isNaN(undefined) // true isNaN(0) // false
 
그런데 동등 연산자 ==의 경우 undefinednull일 때 타입 변환을 시키지 않는다. null == undefined 이렇게 서로를 비교하는 경우가 아니면 false를 반환한다. 이는 undefined는 본인 혹은 null과 비교하지 않는다면 다 false로 반환된다는 것이다. 결국 nullundefined는 대소 관계 비교 연산자의 피연산자로 오지 않는 것이 좋다는 것을 알 수 있다.

References


  1. https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/null
  1. https://2ality.com/2013/10/typeof-null.html