NaN - isNaN - Number.isNaN 조심하기

Devfrank·2023년 1월 22일
2

JavaScript 이슈

목록 보기
1/1
post-thumbnail

NaN - isNaN - Number.isNaN 조심 또 조심...

자바스크립트 so strange.. 10일만에 만들어져서 그런가...?

정의를 보면.. NaN는 'Not-a-Number'의 줄임말. 그러면 number가 아니라는건데...

NaN

  • NaN is not a number.
  • typeof(NaN) should not be a number.
  • console.log(typeof NaN) - "number" 응.....? number 타입이라고..?

isNaN()

  • isNaN() 함수는 값이 NaN(Not a Number)인지 판별한다.
  • false 리턴 하면 숫자, true 리턴하면 숫자가 아니라는건가?
  • MDN에서도 아주 혼란스럽고, 완전히 신뢰할 수 없다고 나온다. ㅋㅋㅋㅋ

Summary: Number() parsing 과정을 거친다.

  • isNaN("") -> 거짓: 빈 문자열은 NaN이 아닌 0으로 변환된다.
  • isNaN(" ") -> 거짓: 공백이 있는 문자열은 NaN이 아닌 0으로 변환된다.
  • isNaN(null) -> 거짓
  • isNaN("37") -> 거짓: "37"은 NaN이 아닌 숫자 37로 변환된다
x					Number(x)	isNaN(x)
undefined				NaN		  true
{}						NaN		  true
'foo'					NaN	      true
new Date('')			NaN		  true
new Number(0/0)			NaN		  true
console.log(isNaN(0)); // false 
console.log(isNaN(1)); // false 
console.log(isNaN('100')); // false 

isNaN(NaN);       // 참
isNaN(undefined); // 참
isNaN({});        // 참

isNaN(true);      // 거짓
isNaN(null);      // 거짓
isNaN(37);        // 거짓

// 문자열
isNaN("37.37");   // 거짓: "37.37"은 NaN이 아닌 숫자 37.37로 변환된다.
isNaN("123ABC");  // 참: parseInt("123ABC")는 123이지만 Number("123ABC")는 NaN.
isNaN("");        // 거짓: 빈 문자열은 NaN이 아닌 0으로 변환된다.
isNaN(" ");       // 거짓: 공백이 있는 문자열은 NaN이 아닌 0으로 변환된다.

// 이것이 허위 양성이고 isNaN이 완전히 신뢰할 수 없는 이유이다.
isNaN("blabla")   // 참: "blabla"는 숫자로 변환.
                  // 이것을 숫자롯 parsing 하는 것을 실패하고 NaN을 반환.

Number.isNaN()

잠깐만.. 정의부터 다시 읽어보자..

  • 주어진 값의 유형이 Number이고, 값이 NaN이면 true, 아니면 false.
  • Number 형에서만 사용가능하고 강제로 Number 변환을 시도하지 않는다.
  • 기존부터 존재한 전역 isNaN() 함수의 더 엄격한 버전.
  • NaN이 NaN인지 계산할 때, 두 동일 연산자 ==과 === 모두 false로 평가되므로 값의 NaN 여부를 알아내려면 Number.isNaN()이 필요함.
                |       Number.isNaN()       |        isNaN()
----------------+----------------------------+-----------------------
value           | value is a Number | result | Number(value) | result
----------------+-------------------+--------+---------------+-------
undefined       | false             | false  | NaN           | true
{}              | false             | false  | NaN           | true
"blabla"        | false             | false  | NaN           | true
new Date("!")   | false             | false  | NaN           | true
new Number(0/0) | false             | false  | NaN           | true
Number.isNaN({});
// <- false, {} is not NaN
Number.isNaN('ponyfoo')
// <- false, 'ponyfoo' is not NaN
Number.isNaN(NaN)
// <- true, NaN is NaN
Number.isNaN('pony'/'foo')
// <- true, 'pony'/'foo' is NaN, NaN is NaN

isNaN({});
// <- true, {} is not a number
isNaN('ponyfoo')
// <- true, 'ponyfoo' is not a number
isNaN(NaN)
// <- true, NaN is not a number
isNaN('pony'/'foo')
// <- true, 'pony'/'foo' is NaN, NaN is not a number

아직도 헷갈리는 부분...

Number.isNaN()는 Number 타입중에 isNaN을 찾는걸로 이해했는데.....

Number.isNaN('pony'/'foo')
// <- true, 'pony'/'foo' is NaN, NaN is NaN
  • isNaN() converts the argument to a Number and returns true if the resulting value is NaN.
  • Number.isNaN() does not convert the argument; it returns true when the argument is a Number and is NaN.

많이 읽어도... 헷갈리는건.. MDN이 이해해주지만 그래도 헷갈린다..

// polyfills
if(!Number.isNaN) {
  Number.isNaN = function(n) {
    if( typeof n === "number" ) {
      return window.isNaN(n)
    } 
    return false
  }
}

Reference

profile
피드백 문화를 지향합니다. Anytime please! 🙌🏻

0개의 댓글