[Javascript] Optional Chaining / Nullish Coalescing
JS Optional Chaining, ?., ??, JS Nullish Optional Chaining
Nullish Coalescing
Nullish Assignment
정의
ES2020 도입의 두 가지 단축 문법.
?.(Optional Chaining) : 중간이 null/undefined 면undefined반환??(Nullish Coalescing) : 왼쪽이 null/undefined 면 오른쪽 사용
Optional Chaining ?.
user?.address?.city
// user 가 null/undefined 면 즉시 undefined
// 그 외에는 평소처럼 평가
// 옛 방식
user && user.address && user.address.city
메서드 호출
obj.method?.() // method 가 없으면 undefined, 있으면 호출
arr?.[0] // 배열 인덱스
fn?.(arg) // 함수 호출
함수 호출 우회
window.callback?.(data) // callback 정의되어 있을 때만 호출
Nullish Coalescing ??
const port = config.port ?? 3000;
// port 가 null 또는 undefined 면 3000, 그 외 그대로
|| 과의 차이:
0 || 'default' // 'default' (0 은 falsy)
0 ?? 'default' // 0 (null/undefined 만 default)
'' || 'fallback' // 'fallback'
'' ?? 'fallback' // ''
null || 'x' // 'x'
null ?? 'x' // 'x'
undefined || 'x' // 'x'
undefined ?? 'x' // 'x'
?? 가 더 명확. 0, ”, false 가 유효한 값일 때 ?? 필수.
Nullish Assignment ??=
obj.a ??= 'default';
// obj.a 가 null/undefined 면 'default' 할당
// 동등: obj.a = obj.a ?? 'default';
다른 단축:
||=: falsy 면 할당&&=: truthy 면 할당
config.timeout ||= 5000; // 0, '', false 도 덮어씀
config.timeout ??= 5000; // null/undefined 만 덮어씀
config.flag &&= 'enabled'; // truthy 면 'enabled' 로
자주 쓰는 패턴
API 응답 안전 접근
const username = response?.data?.user?.name ?? 'Guest';
옵션 객체 default
function api({ timeout, retries } = {}) {
timeout = timeout ?? 5000;
retries = retries ?? 3;
}
콜백 안전 호출
function process(items, { onSuccess, onError } = {}) {
try {
const result = doWork(items);
onSuccess?.(result);
} catch (e) {
onError?.(e);
}
}
배열 / Map 안전 lookup
const first = arr?.[0];
const value = map.get?.(key); // map 자체가 없을 수도
const found = users?.find?.(u => u.id === id);
React state
const name = user?.profile?.name ?? 'Anonymous';
함정
1. ?? 와 || 의 우선순위
a || b ?? c // ❌ SyntaxError (괄호 필요)
(a || b) ?? c // ✓
a || (b ?? c) // ✓
?? 와 || / && 는 함께 쓸 때 괄호 필수.
2. ?. 의 short-circuit
user?.greet().toUpperCase()
// user 가 undefined 면 → undefined.toUpperCase() ❌ TypeError
user?.greet()?.toUpperCase()
// 안전한 chaining
각 단계마다 ?. 필요.
3. 할당의 왼쪽에는 못 씀
obj?.x = 1 // ❌ SyntaxError
if (obj) obj.x = 1;
4. delete 와의 조합
delete obj?.prop
// obj 가 null 이면 무시, 있으면 delete
이건 가능.
5. 0, false, ” 의 처리
function getCount({ count = 10 } = {}) {
return count;
}
getCount({ count: 0 }); // 0 (default 적용 안 됨)
getCount({ count: null }); // null (default 적용 안 됨, ⚠️)
getCount({}); // 10
= default 는 undefined 만 적용. null 처리에 ?? 활용.
function getCount({ count } = {}) {
return count ?? 10;
}
getCount({ count: null }); // 10 ✓
참고
이 글의 용어 (3개)
- [Javascript] 타입 변환 / 강제 변환javascript
- 정의 JavaScript 의 암묵적 형변환 (coercion). 연산자가 양쪽 피연산자의 타입을 자동으로 맞춘다. 명시적 변환과 구분. 3 가지 강제 변환 1. ToString …
- [Javascript] boolean / null / undefinedjavascript
- 정의 JavaScript 의 3 가지 primitive. - : , - : 의도적인 "없음" - : 자동으로 부여된 "없음" (초기화 안 됨) boolean falsy / tru…
- [Javascript] Destructuringjavascript
- 정의 Destructuring 은 배열 또는 객체의 일부를 변수로 풀어내는 ES6 문법. 코드를 짧고 명시적으로. 객체 배열 함수 매개변수 자주 쓰는 idiom API 응답 분해…
💬 댓글