다른 많은 언어와 달리, JavaScript에는 (의미 있는) 값이 없음을 나타내는 두 가지 서로 다른 요소가 있어요. 바로 null과 undefined예요.
원시 값 null은 변수에 의도적으로 "빈 값"을 넣을 때 사용해요. 다른 언어에서는 비슷한 구조가 (없는) 객체나 포인터 타입에만 쓰이기도 해요. JavaScript에서 null은 일반적으로 모든 타입의 빈 값을 나타내요.
let name = null;
// name is intentionally set to "empty" because it is not
// available
엄격한 동등 연산자 ===를 사용하면 변수가 null인지 확인할 수 있어요. null은 원시 값이지만, typeof 연산자는 역사적인 이유로 object를 "잘못" 반환해요. 따라서 이것만으로는 변수가 null인지 확인할 수 없어요.
let name = null;
name === null;
// => true
// Pitfall:
typeof name;
// => 'object'
값을 할당받지 않은 변수는
undefined타입이에요.1
즉, null은 빈 값(하지만 여전히 값)을 나타내는 반면, undefined는 값이 완전히 없음을 나타내요. 🤯
undefined는 다양한 상황에서 나타나요.
undefined예요.undefined를 얻게 돼요.undefined예요.undefined예요. 단, 그 인자에 기본값이 있으면 예외예요.let name;
console.log(name);
// => undefined
let obj = { greeting: 'hello world' };
console.log(obj.missingKey);
// => undefined
function returnNothing() {
return;
}
console.log(returnNothing());
// => undefined
엄격한 동등 연산자 ===나 typeof 연산자를 사용하면 변수가 undefined인지 확인할 수 있어요.
let name;
name === undefined;
// => true
typeof name === 'undefined';
// => true
변수에 undefined를 직접 할당하는 것은 권장하지 않아요. 대신 항상 null을 사용해서 빈 값을 의도적으로 설정했다는 것을 분명히 해요.
위에서 언급했듯이, JavaScript에서 객체에 없는 키에 접근하면 undefined를 반환해요. 하지만 중첩된 값에 접근하려는데 부모 키가 존재하지 않으면, 중첩된 키의 평가가 undefined에서 수행되어 TypeError: Cannot read property ... of undefined가 발생해요. 이론적으로는 중첩된 키를 가져오기 전에 항상 부모 키가 존재하는지 확인해야 해요. 이는 흔히 AND 연산자 &&로 처리했지만, 깊게 중첩된 값에서는 표현식이 매우 길어져요.
obj.level1 && obj.level1.level2 && obj.level1.level2.level3;
이 문제를 해결하기 위해 옵셔널 체이닝이 2020년에 언어 명세에 추가됐어요. 옵셔널 체이닝 연산자 ?.를 사용하면 부모가 null이나 undefined가 아닐 때만 JavaScript가 중첩된 키에 접근하도록 할 수 있어요. 그렇지 않으면 undefined가 반환돼요.
const obj = {
address: {
street: 'Trincomalee Highway',
city: 'Batticaloa',
},
};
obj.residence;
// => undefined
obj.address.zipCode;
// => undefined
obj.residence.street;
// => TypeError: Cannot read property 'street' of undefined
obj.residence?.street;
// => undefined
obj.residence?.street?.number;
// => undefined
변수가 null이나 undefined일 때 기본값을 적용하고 싶은 상황이 있어요. 예전에는 삼항 연산자 ?를 쓰거나 OR 연산자 ||의 지연 평가를 활용해서 처리하곤 했어요. 하지만 이 방식은 변수가 null이나 undefined일 때뿐만 아니라 falsy한 모든 경우(예: ''나 0)에 기본값이 적용된다는 단점이 있어요. 이는 쉽게 예상치 못한 결과를 일으킬 수 있어요.
let amount = null;
amount = amount || 1;
// => 1
amount = 0;
amount = amount || 1;
// => 1
amount = 0;
amount ? amount : 1;
// => 1
이를 해결하기 위해 nullish 병합 연산자 ??가 도입됐어요. 옵셔널 체이닝과 마찬가지로 2020년에 언어 명세에 추가됐어요. nullish 병합 연산자 ??는 왼쪽 피연산자가 null이나 undefined일 때만 오른쪽 피연산자를 반환해요. 그렇지 않으면 왼쪽 피연산자를 반환해요. 덕분에 이제 기본값을 더 정확하게 적용할 수 있어요.
let amount = null;
amount = amount ?? 1;
// => 1
amount = 0;
amount = amount ?? 1;
// => 0
[1] Undefined, MDN. (2021). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined (2021년 6월 4일 확인).