NaN 判定とは何を見分けたいのか
NaN 判定は、「その値が“数値型ではあるけれど壊れた値(NaN)かどうか”」を見分けることです。
NaN は “Not a Number” の略ですが、型としては number です。ここがまずややこしいポイントです。
console.log(typeof NaN); // "number"
JavaScript業務コードでは、計算の途中で NaN が紛れ込むと、その後の計算結果がすべて NaN になり、
しかもエラーにならず静かに壊れていくので、バグの原因としてかなり厄介な存在です。
だからこそ、「NaN かどうかを正しく判定するユーティリティ」がとても重要になります。
なぜ NaN はそんなに厄介なのか
自分自身とすら等しくない
NaN の一番のクセは、「自分自身とすら等しくない」という性質です。
console.log(NaN === NaN); // false
JavaScript普通の値なら x === x は必ず true ですが、NaN だけは false になります。
そのため、「value === NaN で判定しよう」とすると、絶対にうまくいきません。
const value = NaN;
if (value === NaN) {
console.log("NaN です"); // ここには絶対来ない
}
JavaScript「=== NaN では判定できない」というのは、NaN 判定の最初の重要ポイントです。
計算に混ざると全部 NaN になる
NaN が一度計算に混ざると、その後の結果も全部 NaN になります。
const a = NaN;
const b = a + 10;
const c = b * 2;
console.log(a); // NaN
console.log(b); // NaN
console.log(c); // NaN
JavaScriptしかも、エラーにはならず、ただ NaN が伝染していくだけなので、
「どこで NaN が発生したのか」を後から追いかけるのがとても大変です。
だからこそ、「怪しいところで NaN かどうかをチェックする」「NaN を見つけたら早めに止める」という設計が大事になります。
正しい NaN 判定:Number.isNaN
NaN かどうかを判定する正しい方法は、Number.isNaN を使うことです。
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(10)); // false
console.log(Number.isNaN("abc")); // false
console.log(Number.isNaN("10")); // false
console.log(Number.isNaN(Number("abc"))); // true
JavaScriptここでのポイントは、「Number("abc") のように“数値変換に失敗した結果の NaN”を検出できる」ということです。
一方で、単なる文字列 "abc" に対しては false になります。「NaN という値そのもの」を判定しているイメージです。
isNaN(グローバル関数)との違い
歴史的に、Number.isNaN とは別に、グローバル関数 isNaN も存在します。
console.log(isNaN(NaN)); // true
console.log(isNaN("abc")); // true(ここがややこしい)
console.log(isNaN("10")); // false
JavaScriptisNaN は、「一度 Number に変換してから NaN かどうかを見る」関数なので、"abc" のような文字列も「数値に変換すると NaN になるから true」と判定してしまいます。
実務では、この挙動が紛らわしくバグの元になるので、
「NaN 判定には Number.isNaN を使う」と覚えてしまうのがおすすめです。
業務ユーティリティとしての isNaNStrict
プロジェクト内で「NaN 判定は必ずこれを通す」と決めておくと、コードが安定します。Number.isNaN をそのまま使ってもいいですが、名前を付けておくと意図がより明確になります。
function isNaNStrict(value) {
return Number.isNaN(value);
}
console.log(isNaNStrict(NaN)); // true
console.log(isNaNStrict(10)); // false
console.log(isNaNStrict("abc")); // false
console.log(isNaNStrict(Number("abc"))); // true
JavaScriptこの関数は、「値そのものが NaN かどうか」を判定します。
「数値変換に失敗した結果の NaN を検出したい」という場面で使います。
数値変換と NaN 判定をセットで考える
NaN は、たいてい「数値変換に失敗した結果」として生まれます。
例えば、Number や parseInt, parseFloat を使ったときです。
const n1 = Number("10"); // 10
const n2 = Number("abc"); // NaN
console.log(Number.isNaN(n1)); // false
console.log(Number.isNaN(n2)); // true
JavaScript実務では、「変換」と「NaN 判定」をセットで行うユーティリティを用意しておくと便利です。
function toNumberOrNull(value) {
const n = Number(value);
return Number.isNaN(n) ? null : n;
}
console.log(toNumberOrNull("10")); // 10
console.log(toNumberOrNull("abc")); // null
console.log(toNumberOrNull("")); // 0(ここをどうするかは要件次第)
JavaScriptここでは、「NaN になったら null にする」というルールを決めています。
こうしておくと、「NaN が静かに紛れ込む」のではなく、「null として扱う」と明示的に決められます。
計算結果に NaN が紛れ込んでいないかをチェックする
計算の途中で NaN が発生していないかをチェックするのも、実務ではよくやります。
function safeDivide(a, b) {
const result = a / b;
if (Number.isNaN(result)) {
throw new Error("計算結果が NaN になりました");
}
return result;
}
console.log(safeDivide(10, 2)); // 5
console.log(safeDivide(10, 0)); // Infinity(ここは要件次第)
console.log(safeDivide(0, 0)); // ここで例外(NaN)
JavaScriptこのように、「この時点で NaN が出ていたらおかしい」という場所で Number.isNaN を挟んでおくと、
バグを早期に検知しやすくなります。
NaN 判定と「数値判定」の違いを整理する
NaN 判定は、「その値が NaN かどうか」を見るものです。
一方で、「数値として扱えるかどうか」を見るユーティリティ(isNumeric のようなもの)とは役割が違います。
例えば、次のような関数を思い出してください(以前やった数値判定の発展形です)。
function isNumeric(value) {
if (typeof value === "number") {
return !Number.isNaN(value);
}
if (typeof value === "string") {
if (value.trim() === "") return false;
const n = Number(value);
return !Number.isNaN(n);
}
return false;
}
JavaScriptここでは、「NaN を除外するために Number.isNaN を使っている」ことが分かります。
つまり、NaN 判定は「数値判定の中の一部」としても重要な役割を持っています。
実務での具体的な利用イメージ
API からの数値レスポンスを検証する
API から数値が返ってくる想定なのに、実際にはおかしな値が混ざることがあります。
async function fetchPrice() {
const res = await fetch("/api/price");
const data = await res.json(); // 例えば { price: "abc" } が返ってきたとする
const price = Number(data.price);
if (Number.isNaN(price)) {
throw new Error("API から不正な価格が返ってきました");
}
return price;
}
JavaScriptここで NaN 判定を挟んでおくことで、「壊れた値がそのまま計算に使われる」のを防げます。
集計処理の途中で NaN を検出する
大量のデータを集計するときも、NaN が紛れ込んでいないかをチェックしたくなります。
function sum(values) {
let total = 0;
for (const v of values) {
const n = Number(v);
if (Number.isNaN(n)) {
throw new Error(`数値に変換できない値があります: ${v}`);
}
total += n;
}
return total;
}
console.log(sum(["10", "20", "30"])); // 60
console.log(sum(["10", "abc", "30"])); // ここで例外
JavaScriptこのように、「NaN を見つけたらすぐに止める」という方針を取ると、
「どこかで NaN が混ざっていたせいで、最終結果だけおかしい」という状況を避けられます。
小さな練習で感覚をつかむ
最後に、自分の手で NaN 判定を試してみると、理解が一気に深まります。
次の値を順番に Number.isNaN に渡して、結果をコンソールに出してみてください。
NaN, 0 / 0, 10 / 0, 10, "10", "abc", Number("abc"), undefined, null
そのうえで、「どのタイミングで NaN が生まれているか」「どこで NaN 判定を挟むべきか」を意識しながら、
自分のプロジェクトの数値処理に Number.isNaN を組み込んでいくと、数値まわりのバグがかなり減っていきます。
