数と非数(NaN)のどちらかを返す処理があり、その後の処理のために、NaN を判断する必要があったので調べた結果 JavaScript にはそうしたチェックを行うための関数があるということで、NaN とはというところも含めてまとめておきます。
#要約
- NaN は非数を表す値である。
-
isNaN()
関数は誤った解釈をすることがある。 - NaN(非数) かどうかをチェックしたい場合は
Number.isNaN()
を使った方がいい。
#NaNとは
NaN とは、Not a Number の略で、つまり「数ではない」値のことです。
Wikipedia の NaN の項においては、以下の様に説明されています。
コンピュータにおいて、主に浮動小数点演算の結果として、不正なオペランドを与えられたために生じた結果を表す値またはシンボルである。
Wikipedia:NaN より引用
つまり、計算の結果が浮動小数点数だけで表現できない場合に返す値という認識ですかね。
#NaN を返すような処理
var num_1 = 0 / 0; // 0で0を割る
var num_2 = undefined / 10; // 未定義値を割ったりしようとする。
var num_3 = "string" * 10; // 数以外のものを掛けようとする。
var num_4 = Infinity / Infinity; // 無限大で無限大を割ろうとする。
var num_5 = Math.sqrt(-3); // 負の数の平方根を求めようとする。
- これはそのままですね。
- 未定義の値を使って四則演算しようとすると NaN を返します。
- 文字列と数を掛けようとしたり割ろうとしたりすると NaN を返します。引き算もですね。ただし、JavaScript において、足し算に関しては
+
演算子が文字列結合演算子として解釈されるので、文字列と数を足し合わせた文字列が返ってきます。 - これもそのままです。
- これは結果に虚数が含まれており、浮動小数点数のみで表現することができないため、NaN を返すということらしいです。
Wikipedia:NaN より参考
#NaN かどうかを確かめるには
JavaScript において、あるオブジェクトが、NaN を確かめるための組み込み関数やメソッドが用意されています。
##isNaN(val) 関数
isNaN()
関数は値が NaN かどうかをチェックする関数です。
冒頭の要約でも述べたように、この関数は非常にややこしい関数で、 val
を誤検知して間違った値を返す可能性があるため使わない方がいいです。しかし、後の Number.isNaN()
メソッドとの比較のために一応記しておきます。
###サンプル
var val_1 = 100 * 100;
var check_val_1 = isNaN(val_1);
console.log(check_val_1);
// => false
var val_2 = 0 / 0;
var check_val_2 = isNaN(val_2);
console.log(check_val_2);
// => true
上記のサンプルは基本的なものですが、以下のようなパターンもあります。
var val_3 = "100";
var check_val_3 = isNaN(val_3);
console.log(check_val_3);
// => false
isNaN()
関数は、引数が Number 型ではなかった場合、一度 Number 型への型変換を試みるため、false
が返ってくるということです。
今回の場合は、確かにval_3
は、NaN ではないため、これでよいのですが、以下の様な誤検出を招きます。
var val_4 = "string";
var check_val_4 = isNaN(val_4);
console.log(check_val_4);
// => true;
var val_5 = undefined;
var check_val_5 = isNaN(val_5);
console.log(check_val_5);
// => true;
以上のコードではどちらの値も NaN ではないにも関わらず、true
を返しています。
isNaN()
関数にはこうした解釈をするため、使用する際にはこうした仕様を考慮する必要がありますが、こういった誤検出を防ぐためにより堅牢な Number.isNaN()
メソッドがあるので、そちらを使った方がいいです。
MDN web docs mozilla : isNaN()より参考
##Number.isNaN(val)
Number.isNaN()
はある値に対して、NaN で、なおかつ Number 型かどうかをチェックします。どちらも満たすのなら、true
を返しますが、いずれかを満たさない場合は false
を返します。
###サンプル
var val_6 = 100;
var check_val_6 = Number.isNaN(val_6);
console.log(check_val_6);
// => false;
var val_7 = "100";
var check_val_7 = Number.isNaN(val_7);
console.log(check_val_7);
// => false;
var val_8 = 0 / 0;
var check_val_8 = Number.isNaN(val_8);
console.log(check_val_8);
// => true;
isNaN()
関数とほぼ同じように見えますが、Number.isNaN()
は、型変換によって NaN となってしまうパターンに惑わされません。
var val_9 = "string";
var check_val_9 = Number.isNaN(val_9);
console.log(check_val_9);
// => false;
var val_10 = undefined;
var check_val_10 = Number.isNaN(val_10);
console.log(check_val_10);
// => false;
上記はいずれの値も NaN ではないのに isNaN()
関数だと true
を返しますが Number.isNaN()
を使えば、 false
を返してくれます。
MDN web docs mozilla : Number.isNaN()より参考
#まとめ
以上のように、Number.isNaN()
は isNaN()
関数よりも堅牢なメソッドであるため、NaN かどうかをチェックしたい場合は Number.isNaN()
を使うべきだということがわかりました。
誤った解釈や誤字などありましたら、ご指摘くださりますと大変ありがたいです。
#参考
Wikipedia : NaN
MDN web docs mozilla : NaN
MDN web docs mozilla : isNaN()
MDN web docs mozilla : Number.isNaN()