LoginSignup
4
7

More than 5 years have passed since last update.

癖あるNaNの判別方法、isNaN関数の問題

Last updated at Posted at 2019-02-18

NaN === NaN

先日入力された文字列を数値に変換するために parseInt()を使用しまして、その際parseIntは最初の文字が数値に変換できない場合 NaNを返すのでそれを利用して数値と数値以外を分けるif文を書こうとしたんですが

サンプル
const test = prompt('数値を入力してください');
const number = parseInt(test);
if(number === NaN){
  alert('不正な値');
} else {
  alert('正常な値');
}

サンプルコード(Codepen)
こんな感じでif文に 変換された値 === NaNという条件式を書いたのですが、実行してみたら全ての文字が正常な値として認識されました、キャンセル押しても正常な値として認識されます。

ちょっと調べてみたら NaN === NaNだと falseが返ってくるようで、 こういう時はisNaNという関数を使うということがわかりました。

なぜfalseと返ってくるのかは以下のサイトで詳しく解説されていました
NaN === NaN が false な理由とutil.isDeepStrictEqual

isNaN関数を使う

サンプル
const test = prompt('数値を入力してください');
const number = parseInt(test);
if(isNaN(number)){
  alert('不正な値');
} else {
  alert('正常な値');
}

サンプルコード

数値以外を入力したら不正な値として認識されるようになりました。


しかし、isNaNにはとある問題があるということがわかりました。

isNaNの問題点

isNaNは、引数が数値ではなかった場合、まず暗黙の型変換によって数値に変換されてしまうようで、以下の記述だとおかしな結果になってしまいます

isNaNの判別
console.log(isNaN(NaN)); //true
console.log(isNaN(1)); //false
console.log(isNaN('NaN')); //true
console.log(isNaN()); //true

サンプルコード
isNaN関数は「数値であることをチェックする関数」ではなく「数値でないことをチェックする関数」であると考えられているようです。

このような問題を解決するためには、 Number.isNaNを使うようです。

Number.isNaN

Number.isNaN
console.log(Number.isNaN(NaN)); //true
console.log(Number.isNaN(1)); //false
console.log(Number.isNaN('NaN')); //false
console.log(Number.isNaN()); //false

サンプルコード

これで、きちんとNaNの時だけtrueが返ってくるようになりました。

しかし、Number.isNaNは、比較的新しく定義されたもの(ECMAScript6から)らしく、ブラウザによっては対応されてないのものもあるそうです、そういう時は、自分でNumber.isNaNを作る必要があります

Number.isNaNを作る

サンプル
Number.isNaN = Number.isNaN || function(value) {
    return typeof value === "number" && value !== value;
}

こういったブラウザ間の機能を埋めることを「ポリフィル(polyfill)」と言うようです。

4
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7