NaN 은 NaN이 아니다 . . . !

삼콩·2022년 5월 31일
1

JavaScript

목록 보기
3/6
post-thumbnail

JS100제 013번 문제
우리 태양계를 이루고 있는 행성은 수성, 금성, 지구, 화성, 목성, 토성, 천왕성, 해왕성으로 총 8개 입니다. 저희는 우리 태양계의 n번째 행성이 무엇인지 알고 싶습니다.

입력으로 행성의 순서를 나타내는 숫자 n이 입력됩니다.
출력으로 그 순서에 해당하는 행성의 이름을 출력해 주세요.

예를들어 1이 입력되면, 첫번째 행성인 수성이 출력됩니다.

**입출력**
입력 : 1
출력 : 수성

답지에는 단순히 arr의 인덱스를 통해 풀도록 나와있었지만, prompt로 입력을 받아 예외처리 하는 걸 해보고싶어 코드를 더 촘촘히 짜보았다. 우선 나의 요구사항은 다음과 같았다.

  1. 사용자에게 입력받은 값이 숫자가 아닌경우, alert를 띄운 후 다시 입력 요구
  2. 사용자에게 입력받은 값의 범위가 1이상 8이하에 벗어나는 경우, alert를 띄운 후 다시 입력 요구

이걸 예외처리 해보는 과정에서 알고있다고 생각했던 부분을 아예 모르고 있었거나, 새롭게 알게된 부분이 있어 정리해보려한다.

⚠️ prompt는 입력값을 문자열로 처리한다!

if (answer > 8 || answer < 1) && typeof answer !== "number") //이렇게 하면 안됨

처음에는 prompt의 입력이 문자열로 처리되는 줄 모르고 typeof가 number형이 아닌 경우, 예외처리를 해주려고했다. prompt는 숫자를 입력해도 문자열로 처리되기 때문에 입력받은 값을 Number()로 감싸주어 number형으로 형변환을 해준후 따로 처리를 해주어야했다.

⚠️ NaN == NaN은 false로 처리한다!

if (Number(answer) == NaN) //이렇게 하면 안됨


난난이 false라니~ 하면서 충격받았던게 엊그제 같은데 바로 까먹고 왜안되지? 하고 있었다. 사실 NaN과 NaN이 false가 나오는게 뭐그리 대수인가 싶었지만 실제로 맞딱뜨려보니 장난아녔다. 브랜든씨 이리좀와바유.

NaN의 비교는 isNaN으로 하지 않는다면 결과를 예측할 수 없다.
NaN으로 비교하지말고 항상 isNaN을 사용해주자 따흑

✔️ 1번째 방법 : isNaN 사용하기

const arr = ["수성","금성","지구","화성","목성","토성","천왕성","해왕성"];
function galaxy() {
  const answer = prompt("숫자를 입력해주세요");
  if (isNaN(Number(answer))) {
    alert("숫자만 입력이 가능합니다.");
    return galaxy();
  } else if (Number(answer) > 8 || Number(answer) < 1) {
    alert("1-8 사이의 수를 입력해주세요!");
    return galaxy();
  }
  console.log(arr[answer - 1]);
}

galaxy();


참고로 아무것도 입력받지 않는 빈값일 경우, null이기 때문에 숫자로 변환해주면 0이된다. 빈값일 경우의 예외처리를 따로해줘야한다면 0일때로 처리해주자. 나는 1-8사이의 수만 입력하도록 되어있기 때문에 따로 처리해줄 필요가 없었따.

✔️ 2번째 방법 : 정규표현식 사용하기

const arr = ["수성","금성","지구","화성","목성","토성","천왕성","해왕성"];
function galaxy() {
  const regExp = /[1-8]/g;
  const answer = prompt("숫자를 입력해주세요");
  if (!regExp.test(Number(answer))) {
    alert("1-8사이의 숫자만 입력이 가능합니다.");
    return galaxy();
  }
  console.log(arr[answer - 1]);
}

galaxy();

정규표현식을 담은 regExp를 만들어주고, test() 메소드를 사용해준다. test()메소드는 정규식과 특정 문자열 사이의 일치에 대한 검색을 수행한다. true 또는 false 를 반환한다. 따라서 1-8까지의 숫자만 가능한 정규표현식을 answer에서 들어온 값과 일치하지않으면 false를 반환하기 때문에 !를 붙여 해당 조건일 시 alert를 띄워줄 수있도록 진행했다.

✔️ 3번째 방법 : isNaN + 함수를 사용하기

const arr = ["수성","금성","지구","화성","목성","토성","천왕성","해왕성"];
const numCheck = (num) => {num > 8 || num < 1}
function galaxy() {
  const answer = Number(prompt("숫자를 입력해주세요"));
  if (isNaN(answer)) {
    alert("숫자만 입력이 가능합니다.");
    return galaxy();
  } else if (numCheck(answer)) {
    alert("1-8 사이의 수를 입력해주세요!");
    return galaxy();
  }
  console.log(arr[answer - 1]);
}
const 범위체크하는함수 = (num) => num > 8 || num < 1
if(범위체크하는함수(num)){
...
}

이건 멘토님이 추천해주신 방법이다. 범위를 체크하는 함수를 만들어서 작성해주는 게 확실히 가독성이 좋고 추후 유지보수에도 좋을 것 같다 :-)

어려웠던 점

test메소드가 문자열과 정규표현식 사이에 일치를 수행해준다고 하는데, 내가 Number()로 숫자 형변환 해준 것을 test에 넣어도 잘 처리가 되어서 어떤 방식으로 값이 처리되고 수행되는지 아직 감이 잘 오지 않는다

참고한 자료

스택오버플로우 : NaN == NaN이 false인 이유
mozila : NaN
Kamang's IT Blog

profile
프론트엔드 세계의 모략을 꾸미는 김삼콩입니다

0개의 댓글