LoginSignup
62
64

More than 5 years have passed since last update.

NaN をなんとかしたい上での諸注意 と global.isFinite() の罠

Last updated at Posted at 2012-10-01

きっかけは JavaScript NaN type is crazy にコメントした事ですが

1. NaN === NaN は false

typeof NaN // 'number'
typeof Inifity // 'number'
typeof -Infinity // 'number'
toString.call(NaN); // '[object Number]'

Infinity == Infinity // true
Infinity == -Infinity // false
Infinity == NaN // false
NaN == NaN // false
NaN === NaN // false (!!)

みんな知ってるね

2. global.isNaN("NaN") は true, global.isFinite("0") も true

で、このNaNInfinity が厄介である為に isNaN()isFinite() がグローバルオブジェクトに用意されているのですが、これもまた罠があります

isNaN(1);  // false
isNaN(NaN); // true 
isNaN("NaN"); // true (!?)

グローバルオブジェクトの isNaN()isFinite() は引数が文字列でも数値型にパースできるもんだとみなして判定に入ります。これ、isFinite() の方が厄介で、ここで無限大ではない(ちゃんと数値演算できる)変数だと判定してそのまま演算してしまうドジを踏みうる。

var test = function(x) {
  if (isFinite(x)) {
    return x + x;
  }
};

test('10'); // "1010"

3. ちゃんと使おう Number.isNaN(), Number.isFinite()

厳格な数値の NaN 判定、あるいは有限数判定にはグローバルメソッドではない Number.isNaN()Number.isFinite() を使いましょう。

isNaN(NaN); // true
isNaN('NaN'); // true
Number.isNaN(NaN); // true
Number.isNaN('NaN'); // false

isFinite(10); // true
isFinite('10'); // true
Number.isFinite(10); // true
Number.isFinite('10'); // false

if (typeof x === 'number') { ... } のようなバリデーションより手っ取り早く、かつ安心ですよ。

4. (追記)「それ IE とかじゃ Number.isNaN() とかないじゃないですかー」「それくらい Polyfill りなさいよ」

現状、IE 以外のブラウザは ECMAScript 6 の仕様にもかかわらず先行実装してくれているけど、 IE 9 以前のブラウザには用意されていません。でも、以下のようなコードで polyfill することはできます。

Number.isFinite = Number.isFinite || function(any) {
  return typeof any === 'number' && isFinite(any);
};

Number.isNaN = Number.isNaN || function(any) {
  return typeof any === 'number' && isNaN(any);
};
62
64
2

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
62
64