2022-12-07 (수)
옵셔널 체이닝(?.) ?
- 객체 내의 key에 접근할 때 그 참조가 유효한지 아닌지 직접 명시하지 않고도 접근할 수 있는 연산자
- 앱을 만들 때 가장 많이 나오는 문법
서버에서 보내주는 객체의 형태가 아래와 같이 생겼다고 가정합니다.
user: {
name: ‘coding’,
age: 20
friends: {
‘bob’: {
name: ‘bob’,
age: 20
},
‘mark’: {
name: ‘mark’,
age: 20
}
}
}
그러면 우리는 bob이라는 친구의 나이 값을 접근하려면
const age = user.friends.bob.age;
이런 식으로 접근을 해야했습니다. 그런데 에러가 날 수 있으니 함수를 통해서 검사를 한 뒤 값을 받아오겠습니다.
function getFriendAge(user){ // user객체를 받아서 age 리턴
if(user === undefined) return undefined;
if(user.friends === undefined) return undefined;
if(user.friends.bob === undefined) return undefined;
return user.friends.bob.age;
}
const age = getFriendAge(user);
에러를 막기 위해서 if문을 통해서 검사를 계속해서 하다보니 이 함수의 목적은 값을 return하는 것인데 함수의 목적이 바로바로 보이지 않게 되었습니다. 이것을 옵셔널 체이닝을 이용한다면 어떻게 될까요?
function getFriendAge(user) {
return user?.friends?.bob?.age;
}
이렇게 하면 함수가 무엇을 의미하는지 바로바로 볼 수 있어서 편하지 않나요?
const user = {};
const userAddress = user.info?.address ?? '모르는 주소'; // '모르는 주소'
객체내의 값에 접근하는 방법에는 두가지가 있습니다. 여태까지 접근하면 (.) 연산자 대신 대괄호 표기법을 통해서 접근할 수 있습니다.
const user = {
info: {
firstName: 'hello world'
}
};
const key = "firstName";
const userName = user.info?.[key];
const some = {
customMethod: function() {
console.log('hello optional');
}
}
let result = some.customMethod?.();
위의 코드에서 customMethod가 참조할 수 없으면 undefined를 반환하고 끝이납니다. 그러면 만약 customMethod가 메서드가 아니라 그냥 값을 가지고 있는 것이라면 어떻게 될까요?
const some = {
customMethod: 'hello?'
}
let result = some.customMethod?.();
// TypeError: some.customMethod is not a function
그러면 함수가 아니라는 타입에러가 뜨게됩니다.
console.log(arr?.[42]); // undefined
console.log(arr[42]); // TypeError: Cannot read properties of undefined (reading '42')
만약 사용자 객체는 꼭 있어야하는데 그 안에 info 의 age는 꼭 필수가 아니라면 아래와 같이 코딩을 해주어야 합니다.
console.log(user?.info?.age) // 이렇게하면 user 객체가 꼭 있어야할 필요가 없다는 뜻입니다.
console.log(user.info?.age); // 이렇게하면 user 객체가 없다면 에러를 뱉을 것입니다.
선언되지 않은 변수에는 옵셔널 체이닝 연산자를 사용하더라도 에러가 뜰 것입니다.
const nestedProps = obj.first && object.first.name
이처럼 중첩구조를 가진 object에서 객체의 속성값을 찾기 위해선 이런식으로 참조를 확인하여야 했었다. 논리 연산자 &&(앰퍼샌드, 좌우가 모두 참일 때 true를 반환)를 이용하여 좌항 연산자가 truty한 경우에만 object.first.name을 불러올 수 있었다.
하지만 이를 간단이 하여서
const nestedProps = obj.first?.name;
으로 표현하여 first의 값이 존재하면 name을 반환하고 없으면 undefined를 반환한다. 이를 풀어서 해석하면
const nestedProp = ((obj.first === null || obj.first === undefined) ? undefined : obj.first.name);
이런 식이 될 수 있겠다.
💟 참고자료