undefined로부터 소중한 변수를 지키는 방법
자바스크립트는 특이하게도 값이 할당되지 않은 변수에 undefined를 할당합니다. 그래서 자바스크립트 객체에 포함되지 않는 키를 통해 객체 프로퍼티에 접근하면 undefined를 뿜습니다. 뭔가가 할당되어 있긴 하기 때문에 이 변수에 접근했다는 것 자체로 에러를 내지 않고 돌아는 갑니다. 막상 그 프로퍼티나 변수를 가지고 무언가를 할 때 undefined로는 할 수 없어 에러가 납니다. 콘솔에 뜬 뭐뭐는 undefined의 프로퍼티가 아니다
라는 식의 에러를 보면 진작에 좀 알려주지 얄밉다는 생각이 듭니다,,
JS 빌런 undefined
const zooObj = {
cat: { age: 4, color: 'orange' },
dog: { age: 7, color: 'black' },
};
console.log(animalsObj.elephant); //undefined - 에러가 나지 않는다
// 막상 그거 가지고 뭐 하려고 하면 에러를 뿜는다
// TypeError: Cannot read property 'age' of undefined
console.log(animalsObj.elephant.age);
function getElephantAge() {
return zooObj.elephant.age;
}
큰 앱에서는 이런 현상이 반복되다 보면 어떤 부수효과로 인해 객체의 프로퍼티가 없어 undefined가 할당되었는지 추적해야 되는 경우가 생기고 꽤 머리가 아픕니다. 값이 할당되지 않았다면 undefined가 아니라 다른 임의의 값이라던가, 다른 거짓값이라도 지정해 줄 수 있다면 예기치 않는 undefined 할당으로 코드의 흐름이 뚝 끊기는 일을 방지할 수 있을 것입니다. 이번 포스팅에서는 변수에 실수로 undefined가 할당되는 것을 방지할 수 있는 자바스크립트 문 법을 간단하게 정리해 보려고요.
물론 타입스크립트가 제공하는 정적 타이핑을 사용해도 해결할 수 있는 문제입니다. 그렇지만 이 포스팅에서는 제안 단계의 혹은 정식 릴리즈된 자바스크립트 문법으로만 예기치 못한 undefined 할당을 방지하는 방법에 대해 서술합니다!
1. default parameter
const defaultZooObj = {
cat: { age: 4, color: 'red' },
dog: { age: 5, color: 'black' },
elephant: { age: 34, color: 'green' },
};
function getElephantAge(zooObj = defaultZooObj) {
return zooObj.elephant.age;
}
const elphantAge = getElephantAge(undefined); //34
함수의 파라미터가 undefined일 경우를 방지하는 방법으로 함수의 기본 매개변수를 사용할 수 있습니다. ES6에 추가된 문법이구요. 함수에서 파라미터가 따로 할당되지 않았을 때뿐만 아니라 undefined가 파라미터에 할당되었을 때도 기본 값으로 설정한 값이 할당됩니다.
실제 앱을 만들 때는 예시로 든 코드블럭처럼 커다란 default 값을 따로 할당해주는 일은 드물 것 같습니다. 타이핑 측면에서 너무 손해인 것 같아요. 중첩된 객체같은 복잡한 파라미터 보다는 원시 타입의 파라미터에 undefined 할당을 방지하는 용도로 사용하는게 더 적합할 것 같습니다.
function addAge(elephantAge = 34, myAge = 25) {
return elephantAge + myAge;
}
addAge(undefined, 20); // 54
addAge(45, undefined); // 70
2. double negation
const elephantAge = !!zooObj.elephant.age; // undefined가 아닌 false
!!
는 자바스크립트에서 전부터 존재했던 논리 연산자의 한 종류입니다. 어떤 형태의 값이든 불리언 값으로 강제 변환되고 값의 참/거짓 여부에 따라서 true와 false가 됩니다. 어떤 부수효과로 인해 elephant의 값이 undefined일 경우, 이 연산자를 통해 elephant에 접근하면 false값을 얻습니다. undefined를 제거할 수 있는 것이죠! 에어비엔비 자바스크립트 스타일 가이드에서 자칫 불필요할 수 있는 삼항연산자의 대용으로 추천하고 있는 문법입니다. bang(!) bang(!) you`re boolean 이런 식으로 기억하면 좋다네요.
3. optional chaining
const elephantAge = zooObj.elephant?.age; //undefined
?
와 함께 체이닝을 하는 이 문법은 릴리즈된 ES문법은 아닙니다. tc39 proposal stage 4에 있어서 아마 곧 정식으로 릴리즈될 가능성이 매우 높은 문법이죠. 이 문법은 undefined 할당 자체를 막는다기 보다는 undefined를 프로퍼티의 키로 참조함으로써(즉 .
를 사용해서) 발생하는 에러를 막아줍니다. undefined에 .
로 접근해도 에러를 발생시키지 않고 대신에 undefined를 뱉습니다.
개인적으로 이 포스팅에서 소개하는 문법 중 가장 유용하다고 생각합니다. 실제 앱 빌드에서 발생하는 undefined 타입 에러는 객체 안 에 어떤 프로퍼티가 예기치 못하게 undefined일 경우일 때 발생합니다. 이런 상황에서 optional chaining을 사용하면 프로퍼티를 평가하는 조건문을 작성하지 않아도 에러를 뿜지 않으면서 프로퍼티의 존재 여부를 알 수 있기 때문입니다.
4. nullish coalescing operator
// undefined가 아니라 0이 할당됩니다.
const elephantAge = zooObj.elephant ?? 0;
// 얼추 위와 같습니다
if (zooObj.elephant) {
return true;
} else {
return false;
}
// optinal chaining과 궁합이 좋습니다.
const elephantAge = zooObj.elephant?.age ?? 0;
??
, 널 병합 연산자는 연산자 왼쪽의 값이 거짓값이라면 연산자 오른쪽의 값을 자동으로 할당합니다. 이 문법도 tc39 proposal의 stage 4에 있습니다. 완전 간결한 조건문 같은 느낌이라 코드의 가독성을 높이는데도 좋고, 객체의 어떤 프로퍼티의 참거짓 여부를 평가해야 한다면 optional chaining과 간단히 같이 쓸 수 있습니다.