2026.09.15 泊まれる場所4,223 立ち寄りスポット46,522 営業中を確認したキャンプ場1,005 note を読む

JavaScriptのNaNは自分自身と一致しない|割引後の金額チェックが、ずっとすり抜けていた理由

注文フォームの金額チェックで、明らかにおかしい数字が素通りしていた。
NaNは自分自身とすら一致しない、という仕様に気づいていなかった。

注文フォームの金額チェック処理に、ずっと素通りしていた一行があった。
合計金額がおかしな値になっていないかを確認する場所で、if (total === NaN) と書いていた。
見た目はいかにも動きそうなのに、この条件は永遠にtrueにならない。

気づいたきっかけは、割引コードの入力欄を空のまま送信したときの動作だった。
合計金額の表示が「NaN円」になっているのに、エラーメッセージは一切出ていなかった。
チェックのコードを疑って初めて、書き方そのものが間違っていたと分かった。

NaNは「数値ではない」のに、型は数値だった

NaNは Not a Number の略で、名前だけ見ると数値の仲間はずれのように思える。
typeof NaN"number" を返す。
数値として扱われる場所に、計算できなかったという結果だけが入っている状態だった。

自分自身と比べても、一致しないという仕様

JavaScriptの数値の等価比較には、IEEE 754という規格の癖がそのまま乗っている。
この規格でNaN同士の比較は常にfalseと定められていて、NaN === NaNNaN == NaN もfalseになる。
僕が書いた total === NaN は、totalが本当にNaNだったとしても、絶対にtrueにならない一文だった。

知識として知っていたはずなのに、自分のコードで踏むまで気づかなかった。
「値がNaNかどうか」を確かめたい場面で、「NaNと等しいか」という発想そのものが最初から成立していなかった。

判定には専用の関数を使う

NaNかどうかを調べるには、Number.isNaN()を使う。
よく似たisNaN()という古い関数もあるが、こちらは判定の前に値を数値へ変換しようとする癖があり、文字列の"abc"のような値までtrueにしてしまう。
数値であることが分かっている変数の中身だけを見たいなら、Number.isNaN()のほうが素直に動く。

今は入力の時点で止めている

合計金額のチェックは if (Number.isNaN(total)) に書き換えた。
ただそれだけでは根本の対策にならないと気づき、割引コードの入力欄で数値に変換できなかった時点でエラーを出すよう、チェックの位置そのものを前へ動かした。
壊れた値を後から見つけるより、壊れた値を作らせないほうが結局早い。

まる子パパ

まる子パパ

会社員。受託開発のエンジニアで、その前は寿司職人・長距離運転手・農業。 技術ブログは、キャンプの合間に踏んだバグと、AI・Web開発の運用の失敗を書いています。 このサイト自体が、開発に携わっているCMS「コンテナ」の稼働中の実例です。 このサイトについて

ほかにも書いています

note・スタンプ

※noteは運営者が個人で書いているものです。

技術ブログ一覧へ戻る