본문 바로가기

개발/Javascript

[Javascript] NaN 알아보기

반응형

NaN에 대해 알아보기

Javascript에서 숫자를 처리하는 방법

NaN에 대해 본격적으로 다루기 전에,

Javascript에서 숫자를 저장하는 방법에 대해 알아볼 필요가 있어요!


위의 이미지는 [ECMA]에서 정한 Number에 대한 정의입니다.

설명을 통해 다음과 같은 정보를 알 수 있어요.

  • Javascript는 IEEE754라는 표준에 따라 Number value를 처리한다.
  • Not-a-Number(NaN), 양수 무한, 음수 무한도 Number value에 속한다. 
IEEE754란?

전기전자공학자협회(IEEE)에서 정한 표준 중 하나입니다.
Javascript는 숫자를 다룰 때 IEEE754에서 정한 표준에 따라 처리하고 있어요.

더 알아보고 싶다면 이전 포스팅을 참고해주세요!
[양수0, 음수0 차이 쉽게 알아보기]

실제로 콘솔에 typeof NaN을 찍어보면 'number'를 출력합니다. 

숫자 1과 동일한 타입을 가지고 있어요.

 


NaN의 특성

IEEE754표준에 따르면 NaN은 다음과 같은 특성을 갖고 있어요.

  • NaN은 어떤 수와도 같지 않다.
  • NaN은 자기 자신과도 같지 않다.

 

따라서 NaN === NaNfalse라는

언뜻 보아서 이해할 수 없는 결과를 출력하게 됩니다. 😯


NaN 처리하는 방법

그렇다면 NaNNaN과 비교할 수 없다면

어떻게 NaN인지 확인할 수 있을까요?

 

isNaN()

isNaN의 로직

Javasciprt에서는 표준 내장 객체로 isNaN함수를 지원합니다.

[mdn : isNaN]

 

isNaN(123) // false isNaN('123') // false isNaN('hello') // true isNaN(true) // false isNaN(null) // false isNaN(undefined) // true isNaN([]) // false isNaN({}) // true

isNaN함수를 사용하여 NaN인지 아닌지 확인할 수 있어요.

 

그런데 조금 의문이 드는 것이 있어요.

  • '123'은 문자열인데 NaN이 아니다.
  • trueboolean인데 NaN이 아니다.
  • nullNaN이 아닌데, undefinedNaN이다.
  • []NaN이 아닌데, {}NaN이다.

이 궁금증을 해결하기 위해서 isNaN의 내부 동작을 살펴봅시다!


[ECMA]에서 설명하는 isNaN의 로직입니다.

1. 파라미터를 Number로 형변환한다.

2. 변환한 값이 NaN이면 true를 반환한다.

3. 그렇지 않으면 false를 반환한다.

 

위의 로직에서 중요한 것은 isNaN의 인수를 Number로 형변환을 한다는 것이에요.

예시로 한번 알아봅시다!

isNaN('123') 로직 따라가기

1. 파라미터 '123'Number로 변환한다.
2. Number('123')의 결과값은 123이다. 즉, NaN이 아니다.
3. 따라서 false를 반환한다.
isNaN('hello') 로직 따라가기

1. 파라미터 'hello'Number로 변환한다.
2. Number('hello')의 결과값은 NaN이다.
3. 따라서 true를 반환한다.

 


 

정리해보자면 

'asdf' undefined {}

위의 세 가지는 Number로 변환했을 때 NaN을 반환하기 때문에 isNaN이 true가 되고,

 

 

123 '123' true null []

위의 네 가지는 Number로 변환했을 때 숫자를 반환하기 때문에 isNaN이 False가 됩니다.

 

Number()의 로직

그렇다면 이어서 궁금해지는 것은

Number()는 어떻게 동작하길래 어떤 것은 숫자를 반환하고 어떤 것은 NaN을 반환하는 것일까요?


ECMA에서 설명하는 Number로 형변환하는 과정입니다. (아까보다 조금 더 길죠..?)

대략적으로 살펴보자면 다음과 같습니다. 

 

1. 인수가 Number 타입이라면 인수를 그대로 반환한다.

2. 인수가 Symbol 또는 Bigint 타입이라면 TypeError를 발생한다.

3. 인수가 undefined라면 NaN을 반환한다.

4. 인수가 null 또는 flase라면 +0을 반환한다.

5. 인수가 true라면 1을 반환한다.

6. 인수가 String 타입이라면 StringToNumber를 수행한 결과값을 반환한다.

7. 인수가 객체타입이라면 특정 조건에 따라 결과값을 반환한다.

(객체타입을 판단하는 조건은 아직 이해하지 못했어요 ㅜㅜ)

 

undefinedNaN을 반환하고 null+0을 반환하는지 궁금하신가요?

그건 ECMA에서 그렇게 하기로 결정한 것이기 때문에 이를 증명하는 방법은 없어요.

 

다만 그 이유를 추론해보자면,,

undefined값이 존재하지 않음을 의미하기 때문에 숫자로 표현될 수 없는 것이고,

null빈 값(이라는 값)을 의미하기 때문에 0과 유사하게 볼 수 있어서 숫자로 표현된 것이라고 생각해요!


복합한 isNaN()

NaN을 비교하고 싶었는데,

isNaN을 이해하기 위해선 Number의 복잡한 로직까지 알아야하네요..🥵

 

MDN isNaN()

그래서 MDN에서도 결과값을 도출하기까지 너무 많은 if문을 거치는 isNaN()는

특별한 경우가 아니면 사용을 지양하고, 그 대신 Number.isNaN()을 사용하는 것을 제안하고 있습니다.


Number.isNaN()

Number.isNaN()은 표준 내장 함수인 isNaN()보다 간단하고 엄격하게 판단해요.

1. 인수가 Number타입이 아니라면 false를 반환한다.

2. 인수가 NaN이라면 true를 반환한다.

3. 그 외에는 false를 반환한다.

 

Number.isNaN('123') 로직 따라가기

1. 인수 '123'은 String 타입이기 때문에 false를 반환한다.
Number.isNaN(123)로직 따라가기

1. 인수 123은 Number 타입이다.
2. 인수 123NaN이 아니다.
3. 따라서 false를 반환한다.
Number.isNaN(NaN)로직 따라가기

1. 인수 NaN은 Number타입이다.
2. 인수 NaNNaN이기 때문에 true를 반환한다.

isNaN()과 Number.isNaN() 차이

isNaN()과의 가장 큰 차이점은 Number.isNaN()은 형변환을 하지 않는다는 것이에요.

그래서 isNaN()에서는 true를 반환하는 값도

Number.isNaN()에서는 false를 반환하는 경우도 있습니다.

value isNaN(value) 결과 Number.isNaN(value)결과
NaN true true
undefined true false
{} true false
[] false false
[1,2,3] true false
[123] false false
123 false false
'123' false false
'' false false
'abc' true false
true false false
false false false

마치며

평소에 isNaN()Number.isNaN()의 차이를 깊이 생각하지 않고 개발을 했었어요.

 

방금 찾아보니 이런 코드도 작성했더라구요. 🤣

isNaN(Number(value)) // 어짜피 isNaN이 형변환을 해주는데, Number로 굳이 형변환을 해주었다. // isNaN의 동작을 이해하지 못하고 짠 코드이다.

반면 이런 코드는 적절한 사용법입니다.

// 두 인수가 number 타입인 것을 보장한다. // 단, number 타입 중 연산이 되지 않는 NaN의 경우에만 error를 반환한다. // 깔끔하고 안정적인 함수이다. const add = (a: number, b: number) => { ​​if (Number.isNaN(a) || Number.isNaN(b)) return 'error' ​​ ​​return a + b } add(Number(x), Number(y))

역시 기본을 알아야 더 좋은 코드를 작성할 수 있고,

나아가서 어떤 것이 좋은 코드인지 분별할 수 있게 되는 것 같습니다!

 

처음엔 음수0과 양수0가 어떤 차이가 있는지 궁금해서 검색해보기 시작했는데,

질문이 꼬리에 꼬리를 물며 이 글까지 작성하게 되었네요.

 

저와 비슷한 궁금증을 갖고 계셨던 분들께 조금이나마 도움이 되었길 바라요. ☺️


추천글

 

[Javascript] 양수0, 음수0 차이 쉽게 이해하기

+0과 -0 알아보기수학적으로 0은 음수와 양수의 사이에 차이가 없기 때문에 같은 값으로 봅니다.하지만 컴퓨터 세계에서는 `+0`과 `-0`은 엄밀히 말하면 다릅니다.javascript 콘솔에서 `-0`을 입력하면

shelly-log.tistory.com

 

[Javascript] 0.1 + 0.2가 0.3이 아닌 이유 쉽게 이해하기

지난 글 복습하기지난 포스팅에서 javascript에서 `-0`이 존재하는 이유에 대해 알아보았어요.[양수 0, 음수 0 차이 쉽게 이해하기] 위의 글에서 이야기했던 `-0`이 존재하는 이유와 오늘 글의 주제와

shelly-log.tistory.com

 

반응형