JavaScript 에는 유독 null 체크 방법이 다양하고, 예상 외의 작동이 존재한다 👩‍💻

색상 표를 위해 스크린샷과 첨부 파일로 대체한다. 😯😯 편의상 default value 는 'default'라는 string 으로 통일합니다. TypeScript 에서는 동일 타입으로 지정해줘야한다. 💁‍♀️ 하지만 우리가 TypeScript 에서 타입을 지정한다 해도 결국 실행 시점에는 JavaScript 로 transpile되므로 결국 JavaScript 의 동등 비교 및 체크의 넓은 범위를 모두 이해해야한다.

빨간색 칸: 에러 또는 예상과 다른 case 가 출력되는 경우
초록색 칸: 의도한 바에 맞는 null, empty value 체크가 가능한 경우


1. ==를 이용한 null check

double-equal-simple double-equal-everything

Uncaught SyntaxError: Unexpected token ‘==’

위 표에서 볼 수 있듯이 ==은 JavaScript 에서 동등 비교를 하는데 적절하지 못한다. 얼핏 보면 0과 ‘0’, 1과 ‘1’을 구분하지 않고 받고 싶을때 유용해 보일 수도 있지만 2와 ‘2’는 다르다, 또한 0과 false, 1과 true 를 구분하지 못 하고 모두 동등 비교가 성립되므로 JavaScript에서 동등 비교시 ==는 사용하지 말아야한다.

2. ===를 이용한 null check

triple-equal-simple triple-equal-everything

Uncaught SyntaxError: Unexpected token ‘===’

이번에는 매우 아름다운 표를 볼 수 있다. 단, 이 경우에도 주의해야 할 것이 있다.

  • NaN === NaN은(는) 성립하지 않는다.
  • {} === []은(는) Uncaught SyntaxError 가 발생한다.

그렇다면 NaN의 동등 비교는 어떻게 해야할까?

Number.isNaN();
isNaN();  // Number는 생략 가능하다.

를 통해 할 수 있다.

isNaN(NaN);           // true
isNaN(undefined);     // true
isNaN({});            // true
isNaN(function(){});  // true

하지만 메서드 이름과 달리 아름다운 결과를 보여주진 않는다. 💢💢

따라서 정말 NaN인지만 정확히 판단하고 싶다면 다음과 같이 조건을 두 가지를 사용해야한다.

const checkNaN = input => ((input !== NaN) && Number.isNaN(input));
checkNaN(NaN);           // true
checkNaN(undefined);     // fasle
checkNaN({});            // false
checkNaN(function(){});  // false

사실 input !== NaN을 별도로 실행해보면 모든 경우 true 가 반환된다. 하지만 위와 같이 isNaN과 && 연산을 하면 NaN을 제외하면 모든 경우의 수에서 false 조건이 된다는 것을 알 수 있다. 따라서 위 로직을 통해 정확한 체크가 가능하다.

&& 앞위 순서는 바뀌어도 결과에 영향을 미치지는 않지만
&& 연산의 경우의 둘 중 false 일 확률이 높은 것이 앞에 와야 확률상 유리하다
❗️


3. Logical NOT Operator(!)

logical-not

개인적으로 null, not null check 시 유용하게 사용하고 있다!! 👏👏👏 위 1, 2와 달리 동등비교는 아니고 null, not null 체크 시에 활용하기 좋은 방법이다. 동등 비교시에는 null, undefined, NaN, ‘‘의 경우의 수를 각각 체크해야했지만 !를 사용하면 그럴 필요가 없다.

표를 보면 알 수 있듯이 그 어떤 경우에도 SyntaxError가 발생하지 않으며 값 자체가 true, false같은 boolean 값이 들어올 때를 제외하면 0인 경우의 수만 조심하면 대부분의 상황에서 손쉽게 체크가 가능하다. 만약, 0인 경우의 수가 존재할 가능성이 있다면 다음과 같이 조건을 하나만 더 추가해주면 좀 더 완벽한 체크가 가능하다.

참고로 0인 경우는 value === 0 또는 value !== 0 조건을 추가해 제거할 수 있고, true, false 와 같은 Boolean 값은 typeofconstructor를 통해 체크할 수 있다.

좀 더 완벽한 !를 위한 함수

const runWhenEmpty = input => {
    if (!input && (typeof input !== "boolean") && (input !== 0)) {
        console.log("empty!!")
    }
}

좀 더 완벽한 !!를 위한 함수

const runWhenNotEmpty = input => {
    if (!!input || (typeof input === "boolean") || (input === 0)) {
        console.log("not empty!!")
    }
}

하지만 굳이 저런식으로 조건을 복잡하게 나열할 할 필요 없이 !, !!만 체크한 후 try-catch를 이용해 로직을 보호해주는 방법이 더 깔끔하고 안전한 코딩이 가능하다.

4. Nullish Coalescing Operator(??)

nullish-coalescing

1. {} : Uncaught SyntaxError: Unexpected token ‘??’
2.1 function(){} : ‘Anonymous function’ 일 경우 » Uncaught SyntaxError: Function statements require a function name
2.2 function(){} : ‘Named function’ 일 경우 » Uncaught SyntaxError: Unexpected token ‘??’

{} 또는 function(){}일 때 에러가 발생하긴 하지만 valuedefault를 처리하기 위한 용도로 사용되기 때문에 거의 완벽하게 사용이 가능하다. undefinednull일 때만 default value를 반환한다는 것을 기억하자.

5. Default function parameter(편의상 JavaScript 를 기준으로 합니다 👻👻👻)

const nullCheck = (input = 'default') => console.log(input);

default-function-parameter

이름 그대로 parameterdefault value를 지정하는 것이다. 함수 block scope 에 들어가기도 전에 에러를 발생하지 않는 유연함은 있지만 비슷해 보이는 ??와 달리 undefined일 때만 default value를 반환한다는 것에 유의하자. 👀

6. OR Operator(||)

or-operator

?? 보다는 !를 사용하는 것과 비슷하다. !Ternary Operator를 결합해 사용하면 다음과 같다.

let value;
!value ? 'default' : value;

Summary

triple-equal-simple summary

모든 것을 다 기억하긴 어려우니 이것만 기억하자. 🤓🤓

Numbers: javascript null check
Excel: javascript null check