본문 바로가기

[모던JS] 016. [기본] nullish 병합 연산자

codeConnection 2024. 3. 28.

원문

nullish 병합 연산자(nullish coalscing operator) '??"는 최근에 추가된 문법이다. 호환성을 검토해야 할 수 있다.

nullish 병합 연산자 기본형

a ?? b

평가 결과

  • a가 null도 아니고 undefined도 아니라면 무조건 a.
  • 그 외의 경우는 b.

즉 둘 다 null이나 undefined여도 우항을 반환한다.

예시

만약 nullish 병합 연산자를 사용하지 않으면 아래와 같이 길게 작성해야 한다.

// ??를 사용하지 않았을 때
x = (a !== null && a !== undefined) ? a : b;

// ??를 사용했을 때
x = a ?? b

온라인에서 회원가입을 할 때 user가 이름에 대한 모든 정보를 입력하지 않아도 되게끔 하고, 입력하지 않으면 익명의 사용자라고 지칭하고자 할 때도 ?? 병합 연산자를 사용하면 간결하다.

즉, 비어있는 값, 데이터로서 의미가 없는 null이나 undefined를 제외하고 실질적인 데이터가 있는 변수를 골라낼 때 사용한다.

let firstName = null;
let lastName = null;
let nickName = '바이올렛';

console.log( firstName ?? lastName ?? nickName ?? "익명의 사용자"); // 바이올렛

코드해석

  1. ?? 병합 연산자는 좌측에서부터 비교를 시작하는데, 좌항이 null이나 undefined가 아니면 좌항을 반환하고, 맞다면 우항을 반환한다.
  2. 좌항 firstName이 null이기 때문에 오른쪽으로 진행한다.
  3. lastName과 nickName을 비교한다. 좌항인 lastName이 null이므로 우항을 반환한다. 우항은 '바이올렛'이다.

??와 ||의 차이

  • || 연산자
    • truthy한 값을 찾아내서 truthy한 값을 반환한다. truthy한 값이 없을 경우 가장 마지막 피연산자를 반환한다.
  • ?? 연산자
    • null, undefined가 아닌 값을 찾아내어 반환한다. 만약 모든 피연산자가 null이나 undefined가 아니라면 좌항을 반환한다.

대부분의 상황에서 두 연산자는 비슷하게 작동하지만, 피연산자에 0이 들어가는 순간 값이 달라진다. 0은 null도 아니고 undefined도 아니고 단순히 falsy한 값이기 때문이다.

height = height ?? 100;

위 예제에는 height라는 변수가 지정되지 않았다. 따라서 height는 undefined 상태이고 100이 height에 할당된다.

let height = 0;

console.log(height || 100); // 100
console.log(height ?? 100); // 0

위 예제를 보면 height || 100의 비교에서는 height가 0이고 falsy한 값이기 때문에 우항의 truthy한 값인 100을 반환한다.
그리고 height ?? 100에서는 height가 0이고 null이나 undefined 상태가 아니기 때문에 0을 반환한다.

??의 우선순위

??의 연산 우선순위는 5로 많이 낮다.

=와 ?보다만 먼저 연산되고 나머지보다 뒤에 연산된다. 따라서 ??를 사용할 땐 소괄호 () 를 사용하는 것이 좋다.

let height = null;
let width = null;

let area = (height ?? 100) * (width ?? 50);

console.log(area); // 5000

만약 소괄호로 묶지 않았다면 100 * width가 먼저 계산됐을 것이다. null은 숫자형으로 형 변환될 때 0으로, undefined는 NaN이다. 즉 0 * 0은 0이므로 0이 먼저 계산되고, 결국 표현식은 0이 반환된다.

nullish 병합 연산자와 논리 연산자의 혼용 불가

새로 생긴 문법이기 때문에 개발자가 ||를 ??로 바꾸는 과정에서 발생하는 휴먼 에러를 막기 위한, 안정성 이슈로 ?? 병합 연산자는 &&, || 논리 연산자와 함께 사용할 수 없다. 단 소괄호로 섞이지 않도록 구분하면 사용 가능하다.

let x = (1 && 2) ?? 3;

console.log(x); // 2

댓글