NaN を一言でいうと
NaN(ナン)は
「Number(数値)型なんだけど、“正しい数ではない” という特別な値」 です。
名前は Not a Number の略ですが、
「数値じゃない」と言いつつ、型としては number というややこしい存在です。
ここが重要です。
NaN は
「数値計算しようとしたけど、まともな数字にならなかった」という“エラーの結果”を表すための特別な数値
だととらえてください。
NaN はどういうときに出てくるのか
数値に変換できないものを数値計算しようとしたとき
一番よくあるのは、
「数字っぽくない文字列」で計算しようとしたとき です。
console.log("hello" * 2); // NaN
console.log("abc" - 1); // NaN
console.log(parseInt("xyz")); // NaN
JavaScript"hello" * 2 のとき、JavaScript は
「”hello” を数値にして掛け算しよう」としますが、
どうやっても数値にならないので、結果として NaN になります。
0 で割ったとき「必ず」NaN になるわけではない
ここは勘違いしやすいところです。
console.log(10 / 0); // Infinity(無限大)
console.log(-10 / 0); // -Infinity
console.log(0 / 0); // NaN
JavaScript「0 で割った=NaN」ではありません。10 / 0 のように「0 を含まない数を 0 で割る」と Infinity(無限大)になり、
「0 / 0」のように結果が定義できないときに NaN になります。
Math 関数に変な値を渡したとき
console.log(Math.sqrt(-1)); // NaN(実数の範囲外)
console.log(Math.log(-1)); // NaN(対数が定義できない)
console.log(Math.max(1, 2, NaN)); // NaN(中に NaN が混じっている)
JavaScript「数学的に定義できない」ような計算をすると NaN になる、とイメージしておくと良いです。
ここが重要です。
NaN は「エラーそのもの」ではなく
「計算した結果、意味のある数にならなかった」という“結果の値” です。
だから普通の値のように他の計算に混ざって流れていきます。
NaN のやっかいな性質①:何と計算しても NaN が広がる
一度 NaN が混ざると、計算結果も NaN になる
const x = NaN;
console.log(x + 1); // NaN
console.log(x - 1); // NaN
console.log(x * 10); // NaN
console.log(x / 2); // NaN
console.log(Math.sqrt(x)); // NaN
JavaScriptどんな計算をしても、NaN が混ざっていると結果も NaN になってしまいます。
これは、「一度壊れた数値は、以降の計算も信頼できない」 という考え方です。
ここが重要です。
NaN は「数値の世界に生じたウイルス」みたいなもので、
一度入り込むと、その後の計算をどんどん汚染していきます。
だから、“NaN が混ざった時点で早く気付くこと” がすごく大事 です。
NaN のやっかいな性質②:自分自身とすら「等しくない」
NaN === NaN が false になる理由
びっくりポイントです。
console.log(NaN === NaN); // false
console.log(NaN == NaN); // false
JavaScriptNaN 同士を比較しても、「等しい」と判定されません。
つまり、=== NaN や == NaN で NaN をチェックすることはできない
ということです。
これは「NaN は“特定の値”ではなく、“意味のある数じゃない状態”を表している」
という哲学的な理由からそうなっています。
じゃあ、NaN かどうかはどう判定するのか
JavaScript では、
isNaN / Number.isNaN
の 2 つが代表的なチェック方法です。
次の章で違いを説明します。
ここが重要です。
NaN は「唯一、自分自身とすら一致しない値」。value === NaN でチェックしたくなる気持ちをぐっとこらえて、
「NaN 判定には専用の関数を使う」と体に刻んでおくのが大事です。
NaN 判定:isNaN と Number.isNaN の違い
古くからある isNaN(ざっくり判定)
isNaN(value) は、
「その値を数値に変換しようとしてダメだったか?」
を判定する関数です。
console.log(isNaN(NaN)); // true
console.log(isNaN(123)); // false
console.log(isNaN("hello")); // true (数値に変換できない)
console.log(isNaN("123")); // false (数値に変換できる → 123)
console.log(isNaN(undefined)); // true
console.log(isNaN(null)); // false(null → 0 に変換される)
JavaScript"hello" に対して true になるのは、
一度 Number("hello") してみて、それが NaN になるからです。
つまり isNaN は、
「数値に変換してもダメなやつ全部」=「NaN っぽく扱うべきもの」
を true と判断します。
より厳密な Number.isNaN(本当に NaN かだけを見る)
Number.isNaN(value) は、
「その値が、型として number で、かつ中身が NaN かどうか」
だけを見ます。
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(123)); // false
console.log(Number.isNaN("hello")); // false(string なので)
console.log(Number.isNaN("123")); // false
console.log(Number.isNaN(undefined)); // false
console.log(Number.isNaN(Number("hello"))); // true(Number("hello") は NaN)
JavaScriptここが重要です。
実務では、
「既に数値として扱っている値が、NaN になってないか確認したい」 → Number.isNaN を使う
というのが安全です。
isNaN は「何でも数値変換してみてから判定」するので、
「文字列入力をざっくり数値チェックしたい」ときなどに限定して使うとよいです。
NaN が混ざりがちなパターンと対処法
ユーザー入力をそのまま計算に使う
const input = "abc"; // 本当は数字を入れてほしかった
const num = Number(input); // NaN
console.log(num * 2); // NaN(以降の計算が全部 NaN)
JavaScriptここで大事なのは、
「Number(input) した時点で NaN かどうかをチェックする」 ことです。
const input = "abc";
const num = Number(input);
if (Number.isNaN(num)) {
console.log("数値として無効な入力です");
} else {
console.log(num * 2);
}
JavaScript数値と一緒に計算しているのに、途中で NaN になる
例えば、配列の中に混ざった「変な値」。
const nums = [10, 20, "abc", 30];
let sum = 0;
for (const n of nums) {
sum += Number(n);
}
console.log(sum); // NaN(途中で NaN が混ざる)
JavaScriptこの場合も、
Number に変換したタイミングでチェックします。
const nums = [10, 20, "abc", 30];
let sum = 0;
for (const n of nums) {
const value = Number(n);
if (Number.isNaN(value)) {
console.log("数値にできない要素がありました:", n);
continue; // スキップするなど
}
sum += value;
}
console.log(sum); // 60
JavaScriptここが重要です。
NaN は「早期発見・早期隔離」が命。
「数値に変換する入口」で Number.isNaN を使ってチェックし、
そこを通過した値だけを計算に入れるようにすると、バグの連鎖を防げます。
NaN と typeof、Number 型との関係
NaN も typeof すると “number”
console.log(typeof NaN); // "number"
console.log(typeof 123); // "number"
console.log(typeof 1.23); // "number"
JavaScriptNaN も「数値型」の一種です。
「数値としての意味はないけど、型としては number」
という不思議な立ち位置です。
これは
- 0
- 正の数
- 負の数
- Infinity(無限大)
- NaN
のようなものを、全部ひっくるめて「number 型」として扱っているからです。
NaN と null / undefined との違いを整理する
console.log(typeof null); // "object"(歴史的な仕様)
console.log(typeof undefined); // "undefined"
console.log(typeof NaN); // "number"
JavaScriptnull / undefined は
「値そのものが存在しない」系の概念ですが、
NaN は
「数値計算をしようとした結果、まともな数にならなかった」
という立ち位置です。
ここが重要です。
「存在しない」系(null/undefined)と、「計算できなかった」系(NaN)は意味が違う。
NaN は、“数値の世界のエラー状態” を表す値だと整理しておくと、頭がすっきりします。
初心者として NaN で本当に押さえてほしいこと
NaN は Not a Number の略だが、型としては number。
「数値計算の結果が“まともな数にならなかった”ことを表す特別な数値」。
"hello" * 2 や 0 / 0、Math.sqrt(-1) のような「数学的に意味をなさない計算」で NaN になる。
NaN は何と計算しても NaN になり、
さらに NaN === NaN が false になるため、
比較演算子では検出できない。
NaN 判定にはNumber.isNaN(value)(本当に NaN かだけを見る)
を基本として使う。
ここが重要です。
NaN を怖がる必要はありません。
「数値に変換するタイミングで NaN チェックをする」
「計算結果がおかしそうなときは console.log(value, Number.isNaN(value)) してみる」
この 2 つを習慣にするだけで、NaN はむしろ“バグを教えてくれるありがたい存在”になります。
最後に、NaN の挙動を自分の目で確かめるための小さな練習を置いておきます。
const values = ["123", "abc", 0 / 0, 10 / 0, Math.sqrt(-1)];
for (const v of values) {
console.log(
"value:", v,
"| typeof:", typeof v,
"| == NaN:", v == NaN,
"| === NaN:", v === NaN,
"| isNaN:", isNaN(v),
"| Number.isNaN:", Number.isNaN(v)
);
}
JavaScriptこれを実行して結果を眺めると、
「NaN がどう扱われるか」「どの判定が何に反応するか」がかなりクリアに理解できるはずです。
