옵셔널 체이닝 '?.' 파트 링크 : https://ko.javascript.info/optional-chaining
옵셔널 체이닝(optional chaining) ?.을 사용하면 프로퍼티가 없는 중첩 객체를 에러 없이 안전하게 접근할 수 있다.
a 프로퍼티를 누구는 갖고 있고 누구는 갖고 있지 않으면 a 프로퍼티에 접근시 undefined 에러를 뱉는다. 혹은 없는 값을 호출해 null을 반환하는 경우도 있다.
명세서에 ?.이 추가되기 전엔 이런 문제들을 해결하기 위해 주로 && 연산자를 사용했다.
?.은 ?.'앞’의 평가 대상이 undefined나 null이면 평가를 멈추고 undefined를 반환한다.
<script>
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
</script>
위처럼 작성하면 user에 값이 없더라도 에러가 발생하지 않고 undefined를 반환할 뿐이다.
위 예시에서 사용된 user?.는 user가 null이나 undefined인 경우만 처리할 수 있다.
user가 null이나 undefined가 아니고 실제 값이 존재하는 경우엔 반드시 user.address 프로퍼티는 있어야 한다. 그렇지 않으면 user?.address.street의 두번째 피연산자인 address를 찾는 과정에서 에러가 발생한다.
user에 값이 없을 때에만 undefined를 반환하고 넘어가니까.
주의
1. 옵셔널 체이닝을 남용하면 안된다.
?.는 존재하지 않아도 괜찮은 대상에만 사용해야 한다.
위에서 든 예시를 바탕으로 얘기하면 user는 반드시 있어야 하는데 address는 필수값이 아니므로 user.address?.street를 사용하는 것이 바람직하다.
꼭 있어야 하는 값인데 없는 경우에 ?.을 사용하면 프로그래밍 에러를 쉽게 찾을 수 없다.
?.는 왼쪽의 평가대상에 값이 없으면 즉시 평가를 멈춘다.
이런 평가 방법을 단락 평가라고 부른다.
?. 오른쪽에 있는 부가 동작은 ?.의 평가가 멈췄을 때 더는 일어나지 않는다.
?.은 연산자가 아니다. ?.은 함수나 대괄호와 함께 동작하는 특별한 문법 구조체(syntax construct)다.
?.()는 메서드가 존재하는지 여부를 알기 위해 사용한다.
(?.method())
<script>
let user1 = {
admin() {
alert("관리자 계정입니다.");
}
}
let user2 = {};
user1.admin?.(); // 관리자 계정입니다.
user2.admin?.(); // 아무런 에러 없이 그냥 평가가 멈춘다.
</script>
. 대신 []를 사용해 객체 프로퍼티에 접근하는 경우엔 ?.[]를 사용할 수도 있다. (객체.?[key])
<script>
let user1 = {
firstName: "Violet"
};
let user2 = null; // user2는 권한이 없는 사용자라고 가정
let key = "firstName";
alert( user1?.[key] ); // Violet
alert( user2?.[key] ); // undefined
alert( user1?.[key]?.something?.not?.existing); // undefined
</script>
?.은 delete와 조합해 사용할 수도 있다.
이 사용법은 ?. 왼쪽의 값이 존재하면 해당 값을 삭제한다.
delete user?.name; // user가 존재하면 user.name을 삭제한다.
주의! ?.은 읽기, 삭제하기에는 사용할 수 있지만 쓰기에는 사용할 수 없다.
<script>
// user가 존재할 경우를 전제로 작성
user?.name = "Violet";
// SyntaxError: Invalid left-hand side in assignment
// 에러가 발생하는 이유는 undefined = "Violet"이 되기 때문이다.
</script>