
업무를 진행하면서 isNaN(undefined)와 isNaN(null)가 결과가 같을 줄 알고 사용을 했으나 다른 값이 나타나서 확인해봤습니다.
MDN 문서를 확인해봤을 때 “isNaN 함수의 인수가 Number 형이 아닌 경우, 그 값은 먼저 숫자로 강제됩니다.” 라고 작성되어있습니다.
따라서 isNaN이 실행되기 전에 Number 타입으로 강제 변환을 시키게 됩니다.
Number(undefined) // NaN
Number(null) // 0
이 결과가 나타나는 이유는 ECMAScript 문서를 확인했을 때 ToNumber 항목에서 확인할 수 있었습니다.
undefined는 ‘설정되지 않았거나 존재하지 않음'을 나타내며 숫자로 변환할 수 없는 상태이므로 NaN이 반환됩니다.
null은 '의도적으로 값이 없음'을 나타내며 ECMAScript 명세에 따라 숫자 컨텍스트에서는 +0으로 변환됩니다.
isNaN(undefined) // true
isNaN(null) // false
따라서 undefined와 null 은 모두 falsy한 값이지만 isNaN에서 결과가 다른 것으로 나타났습니다.
이러한 동작은 isNaN()의 예상치 못한 결과를 만들어냅니다. 두 값 모두 falsy하지만, ToNumber 과정에서 서로 다른 결과가 나타나기 때문입니다.
그래서 MDN 문서에서는 Number.isNaN을 사용하라고 작성되어있습니다.
Number.isNaN(undefined) // false
Number.isNaN(null) // false
Number.isNaN()은 변형 없이 순수하게 NaN 값인지만 확인합니다. MDN 문서에 따르면 "매개변수를 숫자로 변환하려는 시도를 하지 않아서 숫자가 아니면 언제나 false를 반환합니다."
isNaN()은 내부적으로 ToNumber를 먼저 수행하기 때문에 예상치 못한 결과를 낼 수 있습니다. 순수하게 NaN 값만 확인하려면 Number.isNaN()을 사용하는 것이 Number 유형이 아니라면 false를 반환하기 때문에 isNaN()함수보다 강력합니다.
reference
ECMAScript Language Specification - ECMA-262 Edition 5.1