isNaN()? Number.isNaN()? NaN이 뭔데?

1. NaN이 뭔데?

Not-A-Number의 약자이다. 그렇다 말그대로 숫자가 아닌 값을 말한다.
JavaScript뿐만 아니라 몇몇 다른 언어에서도 다뤄지는 값이지만, 일단 JavaScript에서는 특별한(?) 값으로 취급된다.

Type?

기본적으로 NaN은 원시 타입(primitive type)인 숫자 타입(number type)의 값으로 ECMAScript 스펙에도 엄연히 number type으로 분류되어 있다. - ECMAScript, 6.1.6.1 The Number Type


물론, 좋게 말해 특별한거지 프로그래밍하는 관점에서 보면 이상하다고 볼 수 있다. 무엇이 특별한 것일까?


결론부터 말하면 NaN은 자신과 일치하지 않는 유일한 값이다.

1
2
3
4
5
6
7
NaN === NaN; // false

var nan = NaN;
nan === nan; // false

NaN == NaN; // false
nan == nan; // false

NaN은 동등 비교 연산자(==)이던 일치 비교 연산자(===)이던 어떻게든 같은 값으로 만들어 보려해도 다른 값으로 평가된다.

그렇다면 어떻게 비교할까?



2. isNaN()

isNaN()NaN에 대해 찾아보게된 계기다.

String Type의 값으로 부터 숫자와 기호를 구분한다고 본인은 아래와 같이 짰다.

1
2
3
4
5
6
7
8
let oper = ['+', '-', '*', '/'];
for (let x of s) {
if (oper.includes(s[i])) {
// ...
} else {
//...
}
}

if 4개 박을까, switch 쓸까, ASCII로 비교할까 고민하다 나름 생각한게 이거..

멍청했다. isNaN() 내장 메서드 하나를 새로 배우게 되었다.
그냥 isNaN()을 사용하면 된다.



3. isNaN() vs Number.isNaN()

그런데 isNaN()메서드를 MDN에서 찾아보다가 재밌는 걸 알게되었다.
ES6(ECMAScript 2015)에서는 Number.isNaN()이 추가되었다는 사실.


3.1 왜 추가됨?

isNaN()의 경우 특이 케이스가 몇몇 존재하기 때문에 ES6기반으로 코드를 작성한다면, 특이 케이스가 교정되어 좀 더 strictNumber.isNaN()을 사용할 것을 MDN은 권장하고 있다.


3.2 그래서 정확히 뭐가 다른가?

두 가지 메서드의 용도는 비슷. 차이점은 Number.isNaN()isNaN()에 비해 더 엄격하다

전역 isNaN() 함수와 달리, Number.isNaN()은 강제로 매개변수를 숫자로 변환하는 문제를 겪지 않습니다.
이는 이제 보통 NaN으로 변환됐을 값이 안전하게 전달되지만, 실제로는 NaN과 같은 값이 아님을 의미합니다.
이는 또한 오직 숫자형이고 또한 NaN인 값만이 true를 반환함을 뜻합니다. - MDN


  • isNaN() 메서드는 매개변수를 강제로 Number()로 바꾸는 문제점을 지니고 있음
    게다가 케이스별로 다름

isNaN 함수의 인수가 Number 형이 아닌 경우, 그 값은 먼저 숫자로 강제됩니다.
결과값은 그 뒤에 NaN인지 결정하기 위해 테스트됩니다.
따라서 숫자 형으로 강제된 결과 유효한 비 NaN 숫자값(특히 강제될 때 숫자값이 0 또는 1을 주는 빈 문자열 및 불린 원시형)이 되는 비 숫자의 경우, “false” 반환값은 예기치 않을 수 있습니다 - MDN


예를 들어 이런 상황도 있을 수 있다.

1
2
isNaN('NaN'); // true
Number.isNaN('NaN'); // false

문자열 ‘NaN’을 NaN값인지 확인했는데, 전역함수 isNaN()true라는 말도 예측할 수 없는 결과를 나타냈다.



결론

  • NaN은 JavaScript에서 자기자신과 일치하지 않는 유일한 값이다.
  • NaN은 근본적으로 Number Type이다.
  • NaN인지 확인하는 행위를 의도대로 수행하기 위해서는, Number.isNaN()메서드를 사용할 것을 권장한다,