#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は、引数が数値ではなかった場合、まず暗黙の型変換によって数値に変換されてしまうようで、以下の記述だとおかしな結果になってしまいます
console.log(isNaN(NaN)); //true
console.log(isNaN(1)); //false
console.log(isNaN('NaN')); //true
console.log(isNaN()); //true
サンプルコード
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)」と言うようです。