✔️Optional Chaining(옵셔널 체이닝)이란?
Optional chaining은 객체 체인마다 속성 값이 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성에 접근할 수 있다. Optional chaining 연산자 ?. 를 객체 속성에 접근하거나 함수 호출에서 사용할 때, 객체 속성 값이 nullish(`null` 또는 `undefined`)이거나 함수가 없다면, 연산자 ?. 왼쪽 표현식은 `undefined`로 단락(short-circuiting)되어 에러가 발생하지 않는다.
이렇게 중첩된 객체에서 존재하지 않는 특정 property를 조회할 때 오류 없이 항상 undefined를 반환하고 넘어가게 해주는 문법이 optional chaining이다.
따라서 값이 누락될 가능성이 있는 경우에 옵셔널 체이닝을 사용하면 프로그램의 안정성을 높일 수 있고 보다 간단하게 표현할 수 있다.
✔️Optional Chaining 문법
Optional chaining 연산자 ?. 는 객체, 배열, 함수와 함께 사용할 수 있으며 다음과 같이 4가지 위치에 올 수 있다.
obj?.prop //optional static property access
obj?.[expr] //optional dynamic property access
obj?.[index] //optional array element access
func?.(args) //optional function or method call
✔️Optional Chaining 장점
1. if문을 줄여준다.
서버에서 보내주는 객체의 형태가 아래와 같이 생겼다고 가정해보자.
user: {
name: ‘coding’,
age: 20
friends: {
‘hello’: {
name: ‘hello’,
age: 20
},
‘world’: {
name: ‘world’,
age: 20
}
}
}
그러면 우리는hello라는 친구의 나이 값을 접근하려면 const age = user.friends. hello.age;
이런 식으로 접근을 해야한다. 그런데 에러가 날 수 있으니 함수를 통해서 검사를 한 뒤 값을 받아와보자.
function getFriendAge(user){ // user객체를 받아서 age 리턴
if(user === undefined) return undefined;
if(user.friends === undefined) return undefined;
if(user.friends.hello === undefined) return undefined;
return user.friends.hello.age;
}
const age = getFriendAge(user);
에러를 막기 위해서 if문을 통해서 검사를 계속해서 하다보니 이 함수의 목적은 값을 return하는 것인데 함수의 목적이 바로바로 보이지 않게 되었다. 이것을 옵셔널 체이닝을 이용한다면 어떻게 될까?
function getFriendAge(user) {
return user?.friends?.hello?.age;
}
이렇게 하면 함수가 무엇을 의미하는지 바로바로 볼 수 있어서 편하다.
2. nullish연산자와 함께 쓰면 기본값 주기에 용이하다.
const user = {};
const userAddress = user.info?.address ?? '모르는 주소'; // '모르는 주소'
※ nullish연산자란?
nullish 병합 연산자(nullish coalescing operator) ??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 ‘확정되어있는’ 변수를 찾을 수 있다.
- a가 null도 아니고 undefined도 아니면 a 그 외의 경우는 b
nullish 병합 연산자 ??없이 x = a ?? b와 동일한 동작을 하는 코드를 작성하면 다음과 같다.
x = (a !== null && a !== undefined) ? a : b;
※'??'와 '||'의 차이
nullish 병합 연산자는 OR 연산자 ||와 상당히 유사해보인다. 실제로 위 예시에서 ??를 ||로 바꿔도 그 결과는 동일하다. 하지만 두 연산자 사이에는 중요한 차이점이 있다.
- ||는 첫 번째 truthy 값을 반환한다.
- ??는 첫 번째 정의된(defined) 값을 반환한다.
null과 undefined, 숫자 0을 구분 지어 다뤄야 할 때 이 차이점은 매우 중요한 역할을 한다.
예시를 살펴보자.
height = height ?? 100;
height에 값이 정의되지 않은경우 height엔 100이 할당된다.
이제 ??와 ||을 비교해보자
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
height || 100은 height에 0을 할당했지만 0을 falsy 한 값으로 취급했기 때문에 null이나 undefined를 할당한 것과 동일하게 처리합니다. 따라서 height || 100의 평가 결과는 100이다.
반면 height ?? 100의 평가 결과는 height가 정확하게 null이나 undefined일 경우에만 100이 된다. 예시에선 height에 0이라는 값을 할당했기 때문에 알림창엔 0이 출력된다.
이런 특징 때문에 높이처럼 0이 할당될 수 있는 변수를 사용해 기능을 개발할 땐 ||보다 ??가 적합하다.
3. 대괄호 표기법에도 옵셔널 체이닝이 가능하다.
객체내의 값에 접근하는 방법에는 두가지가 있다. 여태까지 접근하면 (.) 연산자 대신 대괄호 표기법을 통해서 접근할 수 있다.
const user = {
info: {
firstName: 'hello world'
}
};
const key = "firstName";
const userName = user.info?.[key];
4. 존재하지 않을 수 있는 메서드를 호출할 때도 유용하다.
const some = {
customMethod: function() {
console.log('hello optional');
}
}
let result = some.customMethod?.();
위의 코드에서 customMethod가 참조할 수 없으면 undefined를 반환하고 끝이난다. 그러면 만약 customMethod가 메서드가 아니라 그냥 값을 가지고 있는 것이라면 어떻게 될까?
const some = {
customMethod: 'hello?'
}
let result = some.customMethod?.();
// TypeError: some.customMethod is not a function
그러면 함수가 아니라는 타입에러가 뜨게된다.
5.배열에도 사용 가능하다.
onsole.log(arr?.[42]); // undefined
console.log(arr[42]); // TypeError: Cannot read properties of undefined (reading '42')
✔️Optional Chaining 주의할 점
- 지원하지 않는 브라우저에서는 동작하지 않는다. 따라서, 옵셔널 체이닝을 사용하는 경우에는 브라우저 호환성을 고려해야 한다다.
- 옵셔널 체이닝은 프로퍼티나 메서드가 null 또는 undefined인 경우에만 동작한다. 다른 false 값, 예를 들어 0, "", false 등은 체이닝 연산의 결과가 아니라 그대로 반환된다.
- 옵셔널 체이닝을 남발하면 코드 가독성이 저하될 수 있다.
- 옵셔널 체이닝 연산자 ?.는 함수 호출 시 인자로 사용할 수 없다. 대신, 함수 호출 전에 체이닝 연산자를 사용하여 안전하게 객체의 프로퍼티나 메서드를 호출해야 한다.
- 옵셔널 체이닝은 객체 체이닝을 위해 만들어진 것이므로, 배열에서는 사용할 수 없다.(접근만 가능)
참고자료
'Frontend > Javascript' 카테고리의 다른 글
javascript - Hash Table (Object, Map, Set) (0) | 2024.01.23 |
---|---|
DOM과 Javascript (0) | 2024.01.02 |
javascript - Array.from() (0) | 2023.12.26 |
GSAP란 무엇인가? (0) | 2023.11.25 |
javascript - 함수 모음 간단 정리 (0) | 2023.11.18 |