JS/[web] 코어 JS 튜토리얼

[코어 JS] 4.6 - 옵셔널 체이닝 '?.'

web_seul 2021. 10. 11. 11:51
반응형

4.6 옵셔널 체이닝 '?.'

추가된지 얼마되지않은 문법, 구식 브라우저는 폴리필이 필요함

 

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

//1. 여러명의 사용자 중 주소 정보를 가지지않은 사용자가 있을 때 error 발생
let user = {}; // 주소 정보가 없는 사용자
alert(user.address.street); // TypeError: Cannot read property 'street' of undefined

//2. 페이지에 존재하지않는 요소에 접근해 요소의 정보를 가져오려할 때
// querySelector(...) 호출 결과가 null인 경우 에러 발생
let html = document.querySelector('.my-element').innerHTML;

//?.가 추가되기 전 해결 방법
//중첩 객체의 특정 프로퍼티에 접근하기 위해 거쳐야 할 구성요소들을
//AND로 연결해 실제 해당 객체나 프로퍼티가 있는지 확인하는 방법
//코드가 길어진다는 단점
let user = {}; // 주소 정보가 없는 사용자
alert( user && user.address && user.address.street ); // undefined, 에러가 발생하지 않습니다.

 

- 옵셔널 체이닝의 등장

?. 는 '앞'의 평가 대상이 undefined나 null이면 평가를 멈추고 undefined를 반환

//1.
let user = {}; // 주소 정보가 없는 사용자
alert( user?.address?.street ); // undefined, 에러가 발생하지 않습니다.

//2. user객체가 존재하지않아도 에러x
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined

-> ?. 는 '앞' 평가 대상에만 동작되고, 확장은 되지않음 / ?. 는 user가 null 또는 undefined인 경우에만 처리 가능 /  실제값이 존재하는 경우엔 user.address프로퍼티는 있어야함

! 옵셔널 체이닝을 남용하지 마세요

?. 존재하지 않아도 괜찮은 대상에만 사용, user는 필수값이나 address는 필수값이 아니므로 user.address?.street을 사용하는 것이 옳음, 

 

! ?. 앞의 변수는 꼭 선언되어 있어야 함

user가 선언되지 않으면 user?.anything 평가시 에러 발생 _ 옵셔널 체이닝은 let, const, var로 선언이 완료된 변수를 대상으로만 동작

// ReferenceError : user is not defined
user?.address;

 

- 단락 평가(short-circuit)

?. 는 왼쪽 평가대상이 없으면 즉시 평가를 멈추는 단락평가이므로 함수 호출을 비롯한 ?. 오른쪽에 있는 부가 동작은 ?. 의 평가가 멈췄을 때 더는 발생x

let user = null;
let x = 0;

user?.sayHi(x++); // 아무 일도 일어나지 않습니다.

alert(x); // 0, x는 증가하지 않습니다.

 

- ?.() 와 ?.[]

?. 은 연산자가 아닌 함수나 대괄호와 함께 동작하는 특별한 문법 구조체(sysntax construct)

함수 관련 예시와 존재 여부가 확실치 않은 함수 호출시 ?.() 사용 방법

let user1 = {
  admin() {
    alert("관리자 계정입니다.");
  }
}

let user2 = {};

user1.admin?.(); // 관리자 계정입니다.
user2.admin?.();

//모두 user객체는 존재하므로 admin프로퍼티는 .만 사용해 접근
//?.()를 사용해 admin의 존재여부 확인
//user1은 admin이 정의되어 있으므로 메서드가 제대로 호출됨
//user2는 admin이 정의되어 있지않지만 메서드호출시 에러없이 평가가 멈춤
//안전하게 프로퍼티를 읽을 수 있음
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

//.대신 []를 사용해 객체 프로퍼티에 접근하는 경우
//?.[] 사용가능
//객체 존재 여부가 확실하지 않은 경우에도 안전하게 프로퍼티를 읽을 수 있음

 

delete와 조합하여 사용 가능

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

 

! ?.은 읽기, 삭제는 사용가능하나 쓰기는 사용 불가능 _ ?.는 할당연산자 왼쪽에서 사용불가

//user가 존재할 경우
//user.name에 값을 쓰려는 의도로 아래와 같이 코드 작성

user?.name = "Violet"; // SyntaxError: Invalid left-hand side in assingment
//undefined = "Violet"이 되기 때문에 에러발생

 

요약

옵셔널 체이닝 문법 ?. 은 세가지 형태로 사용 가능

1. obj?.prop - obj가 존재하면 obj.prop를 반환하고 그렇지 않으면 undefined를 반환함

2. obj?.[prop] - obj가 존재하면 obj[prop]를 반환하고 그렇지 않으면 undefined를 반환함

3. obj?.method() - obj가 존재하면 obj.method()를 호출하고, 그렇지 않으면 undefined를 반환함

-> ?. 의 왼쪽 평가 대상이 null, undefined인지 확인하고 아니라면 평가를 진행

?. 를 계속 연결해서 체인을 만들면 중첩 프로퍼티들에 안전하게 접근 가능

?. 은 왼쪽 평가대상이 없어도 괜찮은 경우에만 선택적 사용

꼭 있어야 하는 값인데 ?. 를 사용하면 에러해결에 어려움 발생, 주의

 

 

 

 

반응형