🌱 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를 사용하는 것이 바람직하다.