자바스크립트와 같은 동적할당 방식의 언어에서는 타입을 지정하지 않기 때문에 비교적 자유롭게 사용할 수 있는 반면에, 타입이나 에러에 대한 핸들링을 각별히 신경써야 한다. 그런 측면에서 javascript의 옵셔널 체이닝과 null 병합 연산자는
데이터 타입의 동적할당이라는 장점을 최대로 살리면서도, 에러를 관리할 수 있는(?)
유용한 문법이라 할 수 있다.
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
};
const dogName = adventurer.dog?.name;
console.log(dogName);
// expected output: undefined
console.log(adventurer.someNonExistentMethod?.());
// expected output: undefined
위와 같은 코드가 있을 때, dogName은 const dogName = adventurer.dog.name;
처럼 ?
없이 사용하는게 일반적이다. 만약 저런 코드를 쓴다면 adventurer 객체에는 dog라는 프로퍼티가 없으므로 dogName의 출력은 에러를 토해낼 것이다. 하지만 ?
를 활용해 옵셔널 체이닝 문법을 사용하면 dog property가 있는지 확인 후, 없으면 에러를 내지 않고 undefined를 반환한다.
기존 문법에서는 &&
를 통해 처리했었다.
let nestedProp = obj.first && obj.first.second;
옵셔널 체이닝 연산자는 여러번 쌓아서 활용할 수도 있다.
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls" // detailed address is unknown
}
};
let customerCity = customer.details?.address?.city;
// … this also works with optional chaining function call
let duration = vacations.trip?.getTime?.();
null 병합 연산자 역시 옵셔널 체이닝과 비슷하게 에러를 내지 않고 처리하기 위한 핸들링 방법으로 활용할 수 있다.
const description = req.body.description ?? null;
위와 같이 바디의 description에 일치하는 값이 없을 경우 null로 처리하여 에러를 발생하지 않게 할 수 있다.
let customer = {
name: "Carl",
details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
위처럼 옵셔널 체이닝과 null병합 연산자를 함께 사용할 수 있다.
customer?.city?
의 값이 undefined라면 null 병합 연산자에 의해 customerCity 변수의 최종 값은 "Unknown city"가 된다(??
앞의 값이 null이거나 undefined인 경우 ??
뒤에 값 할당).널 병합 연산자 ??
는 연산자 우선순위가 낮은 편이라 ??
는 =
와 ?
보다는 먼저, 대부분의 연산자보다는 나중에 평가된다. 그렇기 때문에 복잡한 표현식 안에서 ??
를 사용해 값을 하나 선택할 땐 괄호를 추가하는 게 좋다.
[javascript] ?. 옵셔널 체이닝 연산자
Optional chaining - JavaScript | MDN
nullish 병합 연산자 '??'