【実務・中級編】 NaN(Not-a-Number)の特性と判定 – JavaScript実践ガイド

現場でコードを書いていると、「数値だと思っていたものが、実は数値じゃなかった」というバグに何度泣かされたことか。

今回は、JavaScript界の「厄介者」でありながら、避けては通れない`NaN`(Not-a-Number)の話をしよう。中級者なら一度はハマるこの落とし穴を、今日で完全に攻略してほしい。

—

1. なぜ「数値」なのに「数値ではない」のか?

まず、大前提として知っておいてほしいのは、`NaN`は「数値ではない」という意味でありながら、型としては`number`であるという矛盾した性質だ。

console.log(typeof NaN); // “number” と出力される。これが全ての悲劇の始まりだ。

`NaN`は、数学的に定義できない計算(`0 / 0`や`Math.sqrt(-1)`など)を行った結果として返される。IEEE 754という浮動小数点数の規格上、これは「数値型の一種」として扱われるからだ。ブラウザのエンジンがこの値を計算結果として返すのは、プログラム全体をクラッシュさせないための「安全装置」のようなものだが、開発者にとってはデバッグの魔物でしかない。

—

2. 最大の罠:`NaN`は自分自身と一致しない

ここがJavaScriptの面白い(そして極悪な)ところだ。`NaN`は、世界で唯一「自分自身と等しくない」値である。

console.log(NaN === NaN); // false

もし君が、「値が`NaN`かどうか」を判定するために `if (x === NaN)` と書いているなら、それは今すぐやめよう。それは一生`false`を返し続ける。かつては`isNaN()`関数が使われていたが、これにも重大な欠陥がある。

古い`isNaN()`の危うさ

`isNaN()`は、渡された値を一度数値に強制変換(暗黙の型変換)してからチェックを行う。これが現場で予期せぬバグを量産する。

console.log(isNaN(“Hello”)); // true (文字列は数値に変換するとNaNになるから)
console.log(isNaN(“123”)); // false (数値に変換できるから)
console.log(isNaN(undefined)); // true (これ、バグの温床になりがち)

「数値がどうかを判定したいのに、文字列の”Hello”まで`true`判定されてしまう」――これでは実務では使えない。

—

3. 実務で採用すべき「正しい判定方法」

モダンなJavaScript環境(ES6以降)で生きる我々が使うべきは、`Number.isNaN()`、あるいはより厳密な`Object.is()`だ。

推奨1:`Number.isNaN()`

これは「型変換を行わない」。純粋に「その値が`NaN`であるか」だけを判定する。これこそが、僕らが求めていた挙動だ。

const value = “Hello”;

// 厳密に判定してくれる
console.log(Number.isNaN(value)); // false (正解!文字列はNaNではない)
console.log(Number.isNaN(NaN)); // true

推奨2:`Object.is()`

`Object.is()`は、`===`演算子とほぼ同じだが、`NaN`の扱いだけが特別に設計されている。「厳密な同値判定」を行いたいなら、これを使うのが最も美しい。

const result = 0 / 0; // NaNになる

// NaNであるかどうかを判定する究極の書き方
if (Object.is(result, NaN)) {
console.log(“計算結果はNaNです。入力値を確認してください。”);
}

—

4. 現場で役立つ実践的なパターン

APIから返ってきたレスポンスをバリデーションする際、僕ならこう書く。

/

  • 数値として妥当かどうかを判定する関数
  • @param {any} value
  • @returns {boolean}

/
const isValidNumber = (value) => {
// 1. 型が数値であること
// 2. NaNではないこと
// 3. 有限数であること (Infinityも弾く)
return typeof value === ‘number’ && Number.isFinite(value);
};

// 使用例
console.log(isValidNumber(100)); // true
console.log(isValidNumber(NaN)); // false
console.log(isValidNumber(Infinity)); // false
console.log(isValidNumber(“100”)); // false (型チェックが効いている)

—

シニアからのアドバイス

`NaN`を扱うときに一番怖いのは、「暗黙の型変換によって、いつの間にか`NaN`が紛れ込んでいる」ことだ。

フロントエンドのフォーム入力や、APIのJSONデータは、常に「予期せぬ型」が入ってくる可能性がある。だからこそ、安易な比較演算子(`==`や`===`)に頼らず、`Number.isNaN()`や`Number.isFinite()`といった、言語仕様が提供する「意図が明確なメソッド」を積極的に使ってほしい。

「動けばいいコード」を書くのはジュニアまで。僕らプロは、「誰が見ても予期せぬ挙動をしない、堅牢なコード」を書く。`NaN`を制する者は、JavaScriptのデータフローを制する。今日のこの知識を、ぜひ明日のコードレビューで活かしてくれ。

コメント

タイトルとURLをコピーしました