on your mark

[JAVASCRIPT.INFO] 4.6 옵셔널 체이닝 '?.' 본문

WEB/Javascript

[JAVASCRIPT.INFO] 4.6 옵셔널 체이닝 '?.'

dev-olive 2022. 12. 28. 22:39

4.6 옵셔널 체이닝 '?.'

최근에 추가됨

옵셔널 체이닝이 필요한 이유

  • 사용자가 여러 명 있는데 그 중 몇명은 주소 정보를 가지고 있지 않다고 가정해보자. 이럴 때 user.address.street를 사용해 주소 정보에 접근하면 에러가 발생할 수 있다.자바스크립트를 사용해 페이지에 존재하지 않는 요소에 접근해 요소의 정보를 가져오려 하면 문제가 발생한다.옵셔널 체이닝이 추가되기 전엔 && 연산자를 사용하여 프로퍼티/객체가 있는지 확인하였지만, 이러한 방법은 코드가 아주 길어진다는 단점이 있다.
  • // querySelector(...) 호출 결과가 null인 경우 에러 발생 let html = document.querySelector('.my-element').innerHTML;
  • let user = {}; // 주소 정보가 없는 사용자 alert(user.address.street); // TypeError 발생

옵셔널 체이닝의 등장

?.?. '앞'의 평가 대상이 undefinednull이면 평가를 멈추고, undefined를 반환한다.

let user = {};
alert(user?.address?.street);    //undefiend, 에러가 발생하지 않는다.

user?.address로 주소를 읽으면 아래와 같이 user 객체가 존재하지 않더라도 에러가 발생하지 않는다.

let user = null;
alert(user?.address); // undefined
alert(user?.address.street) // undefined

usernull이나 undefined가 아니고 실제 값이 존재하는 경우엔 반드시 user.address프로퍼티는 있어야 한다. 그렇지 않으면 user?.address.street의 두 번째 점 연산자에서 에러가 발생한다.

  • ?.는 존재하지 않아도 괜찮은 대상에만 사용해야 한다.
    사용자 주소를 다루는 위 예시에서 논리상 user는 반드시 있어야 하는데, address는 필수 값이 아니므로 user.address?.street를 사용하는 것이 바람직하다.
  • ?. 앞의 변수는 꼭 선언되어 있어야 한다.
    변수 user가 선언되어 있지 않으면, user?.anything 평가 시 에러가 발생한다.

단락 평가

?.는 왼쪽 평가대상에 값이 없으면 즉시 평가를 멈춘다. 이런 평가 방법을 단락평가라고 부른다.

?.() 와 ?.[]

?.은 연산자가 아니다. ?.은 함수나 대괄호와 함께 동작하는 특별한 문법 구조체이다.

let user1 = {
  admin() {
    alert("관리자 계정");
  }
}
let user2 = {};
user1.admin?.();     // 관리자 계정
user2.admin?.();    

두 상황 모두에서 user 객체는 존재하기 때문에 admin 프로퍼티는 .만 사용해 접근하였다.

그리고 난 후 ?.()를 사용해 admin 존재 여부를 확인했다. user2admin이 정의되어 있지 않았음에도 불구하고 메서드를 호출하면 에러 없이 그냥 평가가 멈추게 된다.

. 대신 대괄호 []를 사용해 객체 프로퍼티에 접근하는 경우엔 ?.[]를 사용할 수 있다. 위 예시와 마찬가지로 ?.[]를 사용하면 객체 존재 여부가 확실치 않은 경우에도 안전하게 프로퍼티를 읽을 수 있다.

let user1 = {
  firstName : "Violet"
}
let user2 = null;
let key = "firstName";
alert(user1?.[key]);        // Violet
alert(user2?.[key]);        // undefined

alert(user1?.[key]?.something?.not?.existing)        //undefined

?.delete와 조합해 사용할 수 있다.

delete user?.name;         // user가 존재하면 user.name을 삭제한다.

요약

  1. obj?.prop - obj가 존재하면 obj.prop을 반환, 그렇지 않으면 undefined 반환
  2. obj?.[prop] - obj가 존재하면 obj[prop] 을 반환, 그렇지 않으면 undefined 반환
  3. obj?.method() - obj가 존재하면 obj.method()를 호출, 그렇지 않으면 undefined 반환