Velog
자바스크립트의 논리 할당 연산자: 간단한 문법, 큰 이점
||=, &&=, ??= 의 의미·단락 평가·falsy 함정. "기본값 설정에는 ??=, falsy 덮어쓰기에는 ||=" 규칙 한 문장으로 정리.
핵심 요약
정리:
| 연산자 | 발동 조건 | 의도 |
|---|---|---|
| `a | = b` | |
a &&= b | a 가 truthy | truthy 일 때만 업데이트 |
a ??= b | a 가 null/undefined | 진짜 누락 일 때만 기본값 |
주의:
- 옵셔널 체이닝 좌변 금지:
user?.settings ||= {}→ SyntaxError &&=는 truthy 게이트지만 결과값 으로 덮어씀(원본 유지 X)||=는0/''/false같은 의도된 값 파괴 위험- 우변은 단락 평가되어 side effect 도 절약(
config.apiKey ||= fetchApiKey())
논리 할당 연산자는 "조건부 검사 + 할당" 의 단축형이며, 단락 평가로 오른쪽 표현식이 필요할 때만 평가된다(side effect 안전성). 핵심은 "falsy 인가, nullish 인가" 를 정확히 구분하는 것.
면접에서 let count = 0; count ||= 10 의 결과 같은 코너 케이스가 단골이다. ??= 는 "null/undefined 만" 잡는 반면 ||= 는 0,'',false 까지 덮어쓰는 차이는 버그의 출처 가 된다. 한 번에 정리하면 평생 안 헷갈린다.
학습 포인트
면접 답변으로 연결할 학습 포인트입니다.
`||=` vs `??=` — falsy 와 nullish 의 결정적 차이
let count = 0;
count ||= 10; // count === 10 (0 은 falsy)
count = 0;
count ??= 10; // count === 0 (0 은 nullish 아님)
사용자가 "의도적으로 0 을 넣었나, 그냥 비어 있나" 를 구분해야 하는 곳에서는 반드시 ??=.
"기본값은 ||= 로" 라고 외워서 count/enabled 같은 boolean·숫자 값을 의도치 않게 덮어쓰는 것.
`&&=` 는 "truthy 게이트" 이지만 결과값으로 _덮어쓴다_
let isEnabled = true;
isEnabled &&= false;
console.log(isEnabled); // false
원본 truthy 가 게이트일 뿐, 새 값은 우변 결과(falsy 가능). 이 점에서 if (cond) x = y 와 의미가 같다는 것을 명심.
"truthy 면 그대로 둔다" 라고 오해. 실제는 우변 평가 결과로 대체 된다.
단락 평가가 `apiKey ||= fetchApiKey()` 같은 비싼 호출을 보호한다
config.apiKey ||= fetchApiKey(); // apiKey 가 falsy 일 때만 fetch 호출
user?.settings ||= {}; // ❌ SyntaxError
옵셔널 체이닝의 결과는 참조가 아니라 값 이라 좌변에 올 수 없다. 할당 대상은 항상 참조(변수/속성) 여야 한다.
obj?.x ||= y 로 SyntaxError 만나는 것. 우회는 if (obj) obj.x ||= y 또는 obj && (obj.x ||= y).
읽는 순서
- 1이론
MDN Logical assignment 3개 페이지를 훑고, 각 연산자 발동 조건과 "같은 의미의 if 문" 을 표로 정리.
- 2구현
count = 0,name = '',enabled = false3가지 시나리오에서||=vs??=결과 차이를 콘솔로 확인. - 3실무
현재 프로젝트의
value || default/value ?? default패턴을 grep 해, falsy 보존이 필요한가 기준으로 분류 후 일괄 치환 가능한지 평가. - 4설명
"
||=/??=/&&=의 차이를 코드 예시 1개씩으로 5분 안에" 동료에게 설명. 함정 케이스(0보존,&&=의 결과 덮어쓰기) 도 포함.
면접 연결 질문
[좋은 답변] let count = 0 으로 시작해 ||= 는 10 으로 덮어쓰지만 ??= 는 0 을 유지. 의도된 0 을 보존하려면 ??= 가 안전.
[좋은 답변] isLoggedIn &&= checkPermissions() 에서 checkPermissions 가 false 를 반환하면 isLoggedIn 이 false 로 바뀐다. 즉 권한 검사 후 로그인 자체가 무효 가 되는 부수효과. 의미를 명시하려면 if (isLoggedIn) hasPermission = checkPermissions() 가 더 명확.
[좋은 답변] 좌변은 참조 여야 하는데 obj?.x 는 값 을 반환. 우회: if (obj) obj.x ||= y 또는 (obj ??= {}).x ||= y.
자기 점검
"기본값엔 항상 ||=" — 0/''/false 가 의미 있는 값일 때 깨진다.
"문법이라 안전" — 실제로는 원본 객체를 직접 변경 하므로 history/time-travel 디버깅이 깨진다.