입력 칸에 친 글처럼 프로그램 바깥에서 들어온 값은 늘 문자열입니다. Number()는 글자를 읽어 수 값을 새로 만들고, 수로 읽을 수 없는 글자면 '수가 아님' NaN을 만듭니다. NaN은 오류 없이 계산을 따라 퍼집니다.
웹 페이지의 입력 칸에 20을 쳐도 프로그램이 받는 값은 수 20이 아니라 글자 '20'입니다. 그대로 5를 더하면 25가 아니라 205가 됩니다. 계산하기 전에 글자를 수로 바꿔야 합니다. 이 레슨은 바깥에서 온 글을 따옴표로 감싼 문자열로 두고 연습합니다. 진짜 입력 칸은 폼 제출과 입력 값 레슨에서 만납니다.
1바깥에서 온 값은 글자다
입력 칸에 친 글, 파일에서 읽은 글, 인터넷에서 받아 온 글은 모두 문자열로 들어옵니다. 숫자만 쳐도 따옴표로 감싼 '20'과 같은 글자입니다.
const text = '20';
console.log(text + 5);
console.log(text * 2);
console.log(typeof text);
205
40
string이 단원 첫 레슨에서 본 대로, 2번 줄의 +는 5를 글자로 바꿔 이어 붙이고 3번 줄의 *는 '20'을 수로 바꿔 곱합니다.
같은 글이 *에서는 맞는 값을, +에서는 틀린 값을 냅니다. 그래서 바깥에서 온 값은 계산하기 전에 수로 바꿔 둡니다.
2Number()로 수 만들기
Number()는 괄호 안의 글을 읽어 그 글이 적은 수를 새 값으로 만들어 돌려줍니다.
const text = '20';
const age = Number(text);
console.log(age + 5);
console.log(typeof age);
console.log(text);
25
number
202번 줄은 글 '20'으로 수 20이라는 새 값을 만들고, 이름 age를 그 값에 붙입니다(규칙 2). 그래서 3번 줄의 +는 더하기입니다.
text는 그대로 글자 '20'에 붙어 있습니다. Number()는 글을 고치지 않고 새 수를 만들 뿐입니다.
입력 칸을 비운 채 내면 프로그램이 받는 글은 빈 문자열 ''입니다. 아래 코드는 무엇을 찍을까요? 답을 정한 뒤 펼쳐 보세요.
const text = '';
const age = Number(text);
console.log(age + 5);
실행 결과 보기
5예상과 다르면 그곳이 배울 곳입니다.
2번 줄의 Number()가 빈 문자열을 0으로 읽어 age가 0에 붙습니다. 그래서 3번 줄은 0 + 5를 계산합니다. 오류도 NaN도 나지 않습니다.
Number()는 글 전체가 수 꼴일 때만 수를 만듭니다. 글마다 견주면 이렇습니다.
| 글 | Number() 결과 | 까닭 |
|---|---|---|
'20' | 20 | 수 꼴 |
'3.5' | 3.5 | 소수점도 읽음 |
' 20 ' | 20 | 앞뒤 빈칸은 건너뜀 |
'' | 0 | 빈 문자열은 0으로 읽음 |
'3,000' | NaN | 쉼표는 수 꼴이 아님 |
'20원' | NaN | 수 뒤에 다른 글자가 섞임 |
'스물' | NaN | 수 꼴이 아님 |
빈 문자열 ''이 0이 되는 것은 눈여겨 둡니다. 입력 칸을 비운 채 내도 오류가 나지 않고 0으로 계산됩니다.
다른 자료에서는 parseInt()로 글을 수로 바꾸기도 합니다. parseInt()는 앞에서부터 숫자를 읽다가 숫자가 아닌 글자에서 멈춰, parseInt('12개')는 12입니다. 편해 보이지만 parseInt('3,000')은 쉼표 앞의 3만 읽어 오류도 NaN도 없이 틀린 값 3을 냅니다. Number()는 같은 글에서 NaN을 내어 잘못된 글이라는 표시를 남기므로, 이 과목은 Number()를 씁니다.
3NaN은 오류 없이 퍼진다
수로 읽을 수 없는 글을 Number()에 넣으면 '수가 아님' NaN이 나옵니다. NaN도 수 종류의 값이라 다음 계산에 그대로 들어갑니다.
const bad = Number('스물');
console.log(bad + 1);
console.log(bad * 2);
console.log(typeof bad);
console.log(Number.isNaN(bad));
NaN
NaN
number
trueNaN이 든 계산은 어떤 수를 더하고 곱해도 NaN입니다. 오류로 멈추지 않으니, 틀린 값이 처음 생긴 줄(1번 줄)과 그 값을 알아챈 줄이 멀리 떨어질 수 있습니다.
값이 NaN인지는 5번 줄처럼 Number.isNaN()으로 묻습니다. NaN이면 true, 아니면 false를 돌려줍니다.
두 값이 같은지는 === 기호로 묻습니다(같음과 비교 레슨에서 배웁니다). 그런데 NaN === NaN은 false입니다. NaN은 자기 자신과도 같지 않다고 정해져 있어서, NaN인지 볼 때는 === 기호가 아니라 Number.isNaN()을 씁니다.
예제
도장 카드에 도장이 7개 있고, 오늘 마신 잔 수는 입력 칸에서 글로 들어옵니다. '글을 수로 바꿔 계산'은 글 받기 → 수로 바꾸기 → 계산하기 → 찍기 네 걸음으로 씁니다.
const stamps = 7;
// 1. 글 받기
const text = '2';
// 2. 수로 바꾸기
const cups = Number(text);
// 3. 계산하기
const total = stamps + cups;
// 4. 찍기
console.log('도장', total);
도장 93번 줄은 입력 칸 대신 글자 '2'를 둔 자리입니다. 5번 줄이 그것으로 수 2를 만들고, 그 값에 cups를 붙입니다. 그래서 7번 줄의 +는 더하기입니다.
5번 줄 없이 stamps + text를 계산하면 7 뒤에 글자 '2'가 이어져 도장 72가 찍힙니다. 1번 줄의 stamps는 처음에 한 번 두고 다시 붙이지 않는 고정값입니다.
과목 끝의 할 일 앱에서도 웹 페이지에 적힌 할 일 번호는 글자로 읽혀 Number()로 수를 만든 뒤 쓰고, 남은 개수는 total - done으로 구합니다.
자주 틀리는 곳
틀린 생각: 바깥에서 온 숫자 글은 수처럼 더해진다.
입력 칸에 숫자만 쳤으니 수가 들어올 것 같지만, 바깥에서 온 값은 늘 문자열이라 +가 이어 붙이기가 됩니다.
const text = '20';
console.log(text + 5);
console.log(Number(text) + 5);
205
252번 줄은 글자 '20' 뒤에 5를 이어 205이고, 3번 줄은 Number()가 만든 수 20에 더해 25입니다.
맞는 규칙: 바깥에서 온 값은 무엇을 쳤든 문자열입니다. +로 계산하기 전에 Number()로 수를 만듭니다.
틀린 생각: 비어 있는 글은 수로 바꿀 수 없어 NaN이 된다.
아무것도 없으니 '수가 아님'일 것 같지만, 2절 표처럼 Number('')는 0입니다. 입력 칸을 비운 채 내면 오류도 NaN도 없이 0으로 계산됩니다.
맞는 규칙: Number()는 빈 문자열과 빈칸만 있는 글을 0으로 읽습니다. 그래서 바꾼 값이 0이면 정말 0을 친 것인지 칸을 비운 것인지 갈리지 않습니다. 비었는지는 바꾸기 전의 글로 봅니다.
틀린 생각: 쉼표를 찍은 금액도 Number()가 읽는다.
사람은 '3,000'을 삼천으로 읽지만, Number()에게 쉼표는 수 꼴이 아닌 글자입니다. Number('3,000')은 NaN이고, 그 값으로 한 계산도 모두 NaN입니다.
맞는 규칙: Number()는 글 전체가 수 꼴일 때만 수를 만들고, 쉼표나 '원' 같은 글자가 섞이면 NaN을 만듭니다. 쉼표는 지운 뒤에 바꿉니다(글자를 지우는 법은 '문자열 메서드' 레슨에서).
틀린 생각: NaN인지는 === NaN으로 물을 수 있다.
같은지 묻는 === 기호로 NaN과 견주면 될 것 같지만, NaN은 자기 자신과도 같지 않습니다.
const bad = Number('스물');
console.log(bad === NaN);
console.log(Number.isNaN(bad));
false
truebad는 NaN인데도 2번 줄은 false를 찍습니다. 3번 줄의 Number.isNaN()만 true라고 답합니다.
맞는 규칙: NaN은 어떤 값과 견주어도, 자기 자신과 견주어도 같지 않습니다. 값이 NaN인지는 Number.isNaN()으로 묻습니다.
확인 문제
1. 예제의 3번 줄을 const text = '12';로 바꿨습니다. 무엇이 찍힐까요? 글자 그대로 쓰세요.
const stamps = 7;
// 1. 글 받기
const text = '12';
// 2. 수로 바꾸기
const cups = Number(text);
// 3. 계산하기
const total = stamps + cups;
// 4. 찍기
console.log('도장', total);
힌트
5번 줄이 만든 cups가 글자인지 수인지 먼저 정하세요.
정답
도장 19Number()가 글 '12'로 수 12를 만들어, 7번 줄이 7 + 12 = 19를 계산합니다.
흔한 오답은 도장 712입니다. 5번 줄이 수를 만든 것을 놓치고 글자를 이어 붙인다고 본 것입니다.
2. 예제의 '2. 수로 바꾸기' 줄을 비웠습니다. 도장 9가 찍히도록 빈칸을 채우세요.
const stamps = 7;
// 1. 글 받기
const text = '2';
// 2. 수로 바꾸기
const cups = ____;
// 3. 계산하기
const total = stamps + cups;
// 4. 찍기
console.log('도장', total);
힌트
3번 줄의 text가 붙은 값의 종류부터 정하세요. 빈칸 위 주석이 그 값으로 할 일입니다.
정답
Number(text)입니다. 채우면 예제와 같은 코드가 되어 도장 9가 찍힙니다.
2절 끝의 parseInt(text)나 text * 1도 이 글에서는 수 2를 만들어 같은 결과가 찍힙니다. 이 과목은 무엇을 하는지 드러나고 잘못된 글에서 NaN을 내는 Number()를 씁니다. 2를 직접 써도 같은 화면이 찍히지만, 3번 줄의 글을 바꾸면 따라 바뀌지 않습니다.
흔한 오답은 text입니다. 바깥에서 온 글을 그대로 쓴 것입니다(문자열과 수를 가리지 않는 생각). 그러면 7번 줄이 7 뒤에 '2'를 이어 도장 72가 찍힙니다.
3. 사흘 동안 걸은 걸음 수가 글로 들어왔는데, 화요일은 비어 있고 수요일에는 쉼표가 있습니다. 무엇이 찍힐까요? 세 줄을 글자 그대로 쓰세요.
const mon = Number('4000');
const tue = Number('');
const wed = Number('2,500');
console.log(mon + tue);
console.log(wed);
console.log(mon + wed);
힌트
2절 표에서 빈 문자열과 쉼표가 든 글이 무엇이 되는지 보세요. 그다음 NaN이 든 계산을 떠올리세요.
정답
4000
NaN
NaN빈 문자열은 0이 되어 4번 줄은 4000 + 0 = 4000입니다. '2,500'은 쉼표 때문에 NaN이고, NaN이 든 6번 줄의 더하기도 NaN입니다.
흔한 오답은 첫 줄의 NaN과 셋째 줄의 6500입니다. 빈 글은 NaN이 되고 쉼표 금액은 읽힌다고 거꾸로 본 것입니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
예제를 main.js에 저장해 돌립니다. 그다음 5번 줄의 Number(text)를 text로 바꾸면 무엇이 찍힐지 먼저 적고, 바꿔 돌려서 맞춰 봅니다.
저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.