Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript 배열에서 NaN 값의 위치를 확인하는 방법

배열에는 참(truthy)과 거짓(falsy) 값이 섞여 있을 수 있습니다. 이번 글에서는 원본 배열에서 NaN에 해당하는 요소들의 인덱스를 담은 새로운 배열을 반환하는 함수를 작성해 보겠습니다.

NaN !== NaN이라는 특수한 성질 활용하기

NaN의 데이터 타입은 사실 number입니다. NaN은 거짓(falsy) 값이지만, 다른 어떤 데이터 타입이나 변수와도 다른 독특한 성질을 가지고 있습니다. 바로 NaN === NaN 표현식이 false를 반환한다는 점입니다. 자기 자신과 같지 않은 유일한 값이 바로 NaN입니다.

이러한 동작 방식을 역으로 이용하면 NaN 값을 손쉽게 걸러낼 수 있습니다. 코드는 다음과 같습니다.

const arr = [7, 1, "123abc", undefined, NaN, 78, NaN, null, "aes", NaN,
'', null, NaN];
const pickNaN = (arr) => {
    return arr.reduce((acc, val, ind) => {
        if(val !== val){
            acc.push(ind);
        };
        return acc;
    }, []);
};
console.log(pickNaN(arr));

val !== val 조건은 오직 NaN일 때만 true가 되므로, 이를 통해 해당 요소의 인덱스를 정확하게 추출할 수 있습니다.

isNaN()과 Number.isNaN() 사용하기

isNaN() 함수는 전달된 값이 NaN이거나 NaN으로 강제 변환(coercion)될 수 있는 경우 true를 반환합니다. 반면 Number.isNaN() 함수는 전달된 값이 실제로 NaN일 때만 true를 반환합니다.

따라서 NaN 여부를 확인할 때는 isNaN()보다 Number.isNaN()이 훨씬 신뢰할 만한 방법입니다. 두 함수의 결과 차이를 아래 예제에서 확인해 보겠습니다.

예제

const arr = [7, 1, "abc", undefined, NaN, 78, NaN, null, "aes", NaN, '',
null, NaN];
const pickNaN = (arr) => {
    return arr.reduce((acc, val, ind) => {
        if(Number.isNaN(val)){
            acc.reliableWay.push(ind);
        };
        if(isNaN(val)){
            acc.unreliableWay.push(ind);
        }
        return acc;
    }, {
        reliableWay: [],
        unreliableWay: []
    });
};
console.log(pickNaN(arr));

위 코드는 두 개의 배열을 준비합니다. 하나는 Number.isNaN()을 사용한 결과(신뢰할 수 있는 방식), 다른 하나는 isNaN()을 사용한 결과(신뢰성이 떨어지는 방식)입니다.

출력 결과

{
    reliableWay: [ 4, 6, 9, 12 ],
    unreliableWay: [ 2, 3, 4, 6, 8, 9, 12]
}

결과를 보면 isNaN()이 실제로는 NaN이 아닌 많은 값을 NaN으로 판정한 것을 알 수 있습니다. 문자열 "abc"나 undefined처럼 숫자로 변환 시 NaN이 되는 값들까지 모두 잡아내기 때문입니다. 그렇기 때문에 정확한 NaN 검사가 필요하다면 Number.isNaN()을 사용하는 것이 가장 안전하고 권장되는 방법입니다.