Optional Chaining

kirin.log·2021년 9월 22일
0

🍄 Optional Chaining [?.]


🌱 Optional Chaining 이란?

  • ES2020에서 등장한 새로운 연산자로서 ?. 의 형태로 사용한다.
    연산자를 통한 속성값 접근의 문제점으로, 여러 단계로 이루어진 객체(중첩구조)를 탐색할 때는 항상 TypeError가 발생할 확률이 생기기 때문에 이에 대한 대안으로 등장한 연산자이다.

  • 체인으로 이루어진 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙히 위치한 속성 값을 읽을 수 있는 연산자이다.
    즉, 체이닝 연산자(.)와 비슷하게 동작하지만, 만약 참조가 null 혹은 undefined여도 에러식을 뱉지 않고 undefined값을 리턴한다.
    함수 호출시에도 마찬가지로 값이 없다면 undefined를 리턴한다.

  • Optional chaining을 사용하므로써 문법의 가독성이 올라가고 간결한 표현식으로 작성할 수 있게 된다.
    속성값이 존재한다는 확실한 보증이 없을 경우 그 객체를 탐색하는 데 도움을 준다.

자바스크립트에서는 주로 . 연산자(chaining)를 사용해서 객체의 속성값에 접근한다. 그러나 객체에 접근했을 때 값이 없을 수도 있다(=error).
객체의 속성을 접근할 때, . 연산자 대신에 옵셔널 체이닝(optional chaining, ?.)을 사용하면, 해당 객체가 nullish (= undefined나 null) 인 경우에 TypeError 대신에 undefined를 얻게되어 프로퍼티가 없는 중첩 객체를 에러 없이 안전하게 접근할 수 있다.

🔆 사용 형태

  • 물음표 기호와 온점(?.)을 사용.
  • 참조가 null / undefined 라면, 에러(error) 대신 undefined 리턴.
  • 주어진 함수가 없으면 undefined.
  • 배열이나 함수에도 사용할 수 있다.

🌱 Optional Chaining 사용 예시

🪴 ?.

  • 중첩객체의 속성값에 접근하기 위해 옵셔널체이닝을 적용할 때 ?. 로 표현할 수 있다.
// 객체 (중첩구조)
const animals = { 
  cat: { name: "나비" }, 
  lion: { name: "호랑이" } 
} 

// 중첩구조에서 속성값 읽는 방법 (1) -> 논리연산자 && 활용 (좌항 연산자가 true인 경우에만 우항 연산자를 불러올 수 있다.)
const catName = animals.cat && animals.cat.name;


// 중첩구조에서 속성값 읽는 방법(2) -> optional chaining
const catName = animals.cat?.name;
console.log(catName);  // "나비"

const dogName = animals.dog?.name; 
console.log(dogName); // undefined -> animals에는 dog속성이 없기때문에 dog?.name 도 undefined이다.

🪴 ?.()?.[]

  • 중첩객체의 함수와 배열에 접근하기 위해 옵셔널체이닝을 적용할 때, ?.()(함수) 와 ?.[](배열)로 표현할 수 있다
// user1 객체 내부에는 메서드(함수) admin이 있다
let user1 = {
  admin() {
    alert("관리자 계정입니다.");
  }
}

// user2 객체는 메서드가 없다
let user2 = {};

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

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

. 대신 대괄호([])를 사용해 객체 프로퍼티 키(key)에 접근하는 경우엔 ?.[]를 사용할 수 있다.

❗️객체의 속성(property)에 접근하는 방법에는 2가지가 있다.
1) 점 표기법 : 마침표(.)를 사용하여 객체의 속성값에 접근
2) 대괄호 표기법 : 대괄호([ ])를 사용하여 객체의 속성값에 접근

let obj = {
  one : 1,
  two : 2,
}

console.log(obj["one"] + "vs" + obj.two)
// 1 vs 2

위 예시처럼 2가지 접근법이 모두 사용 가능하다.
단, 점 접근법을 사용할 수 없는 경우도 존재한다. 프로퍼티 키(key) 이름이 유효한 자바스크립트 이름이 아니거나, 숫자로 이루어져있거나, 예약어 인 경우, 프로퍼티 값은 대괄호 표기법으로 읽어야 한다.
대괄호 표기법을 사용하는 경우, 대괄호 내에 들어가는 프로퍼티 이름은 반드시 문자열이어야 한다.

let person = {
  'first-name': 'devvv',
  'last-name': 'Lee',
  gender: 'male',
  1: 10
};

console.log(person.first-name);    // NaN: undefined-undefined
console.log(person[first-name]);   // ReferenceError: first is not defined
console.log(person['first-name']); // 'devvv'

console.log(person.gender);    // 'male'
console.log(person[gender]);   // ReferenceError: gender is not defined
console.log(person['gender']); // 'male'

console.log(person['1']); // 10
console.log(person[1]);   // 10 : person[1] -> person['1']
console.log(person.1);    // SyntaxError

❗️ 옵셔널 체이닝을 남용하지 말자
?.존재하지 않아도 괜찮은 대상(필수값이 아닌 대상)에서만 사용해야 한다.

let user = null;  // user 정보가 없다

alert( user?.address ); // undefined

// user?. 평가가 끝나고 user에 값이 없다는 것이 판별되면, 그 즉시 평가를 멈추기 때문에 아래 두 줄에서 에러가 발생하지 않는다.
// 즉, 평가가 끝나면 나머자 프로퍼티들엔 접근 자체를 하지 않기 때문이다. 
  
alert( user.address?.street ); // undefined
alert( user.address?.street.anything ); // undefined

// 다만 user가 존재하는 경우엔 user.address 같은 중간 프로퍼티들이 평가대상이 되기 때문에 반드시 값이 있어야 에러가 발생하지 않는다.         

위 예시에서 논리상 user는 반드시 있어야 하는데, address는 필수값이 아니다.
그러니 user.address?.street를 사용하는 것이 바람직하다.

profile
boma91@gmail.com

0개의 댓글