この記事は技術レビューを必要としています。ぜひご協力ください。
この記事は編集レビューを必要としています。ぜひご協力ください。
isNaN() 関数は引数が NaN (非数)かどうかを判定します。isNaN 関数の型強制は興味深いルールを持つことに注意してください。値が非数かどうかを判定する代用方法として、ECMAScript 6 で定義されている Number.isNaN() や typeof が使用できます。
構文
isNaN(testValue)
引数
testValue- テストされる値。
説明
isNaN() 関数は、トップレベル関数であり、どのオブジェクトとも関連付けされません。
isNaN() 関数は、渡された引数を数に変換できるかどうかを試みます。その引数が変換できなかった場合、true を返します。そうでない場合は、false を返します。
isNaN 関数の必要性
JavaScript にあるその他すべての値とは違い、ある数値が NaN であるかの判定に等値性評価演算子(== と ===)を使用する方法は信頼性に欠けます。なぜなら NaN == NaN と NaN === NaN はどちらも false と評価されるからです。そこで、isNaN が必要となります。
NaN 値の生成条件
NaN の値は算術演算の結果が未定義か表現不可能な値となった時に生成されます。こうした値が常にオーバーフロー状態を表現するわけではありません。NaN はプリミティブな数値が利用不可能といった、非数値を数値へと型強制した結果生成されることもあります。
例えば、ゼロをゼロ除算した場合の結果は NaN になりますが、その他の数をゼロ除算した場合は異なります。
特殊な場合における厄介な動作
isNaN 関数の定義はごく初期のバージョン以降、数値ではない引数における振る舞いが分かりにくいものとなっていました。isNaN 関数の引数が 数値型ではない場合、その値はまず数へと型強制されます。その結果の値はその後 NaN かどうかがテストされます。このようにして、数値型に型強制される際に結果が NaN ではない数値となる非数値(とりわけ型強制されると 0 や 1 の値になる空文字列や真偽値プリミティブ)に対しては、予想外なことに "false" が返されます【訳注: 「NaN でない」という結果から「数値である」と誤って解釈されてしまう】。無論、例えば空文字列は「数ではありません」。この混乱は、"not a number" (数ではない)というこの用語が IEEE-754 浮動小数点数定義で表現された数において特別な意味があるという事実に起因しています。この関数は、「この値を数値型に型強制した場合、IEEE-754 における 'Not A Number' という値になりますか?」という質問に答えるものとして解釈すべきです。
ECMAScript 6 では Number.isNaN() 関数が導入されます。Number.isNaN(x) は x が NaN かどうかをテストする確実な方法となる予定です。しかしながら Number.isNaN においても、NaN の意味は単純ではない明確な数値的意味を持つ "not a number" のままです。Number.isNaN が利用できない場合、x が NaN かどうかを確実にテストする代わりの方法として (x != x) という式があります。この式の結果は信頼性のない isNaN が引き起こす誤検出の影響を受けません。
使用例
isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: "37" は非数でない数値 37 に変換される
isNaN("37.37"); // false: "37.37" は非数でない数値 37.37 に変換される
isNaN(""); // false: 空文字列は非数でない 0 に変換される
isNaN(" "); // false: 半角スペースからなる文字列は非数でない 0 に変換される
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
// isNaN が信頼性に欠ける理由となる誤検出の例
isNaN("blabla") // true: "blabla" が数値に変換される。
// 数値への変換が失敗し NaN が返される。
特殊な場合における便利な動作
isNaN() のふるまいを考慮した別の使用方法があります。isNaN(x) が false を返す場合、NaN を返すことなく算術式内で x を使用できます。true を返す場合、x を使用すると全ての算術式で NaN を返すことになります。これはつまり、JavaScriptにおいて isNaN(x) == true という式は、x - 0 という式が NaN を返すかどうか、というケースと同等である(JavaScript では x - 0 == NaN は常に false を返すため、このことを確認できませんが)ということです。実際、isNaN(x)、isNaN(x - 0)、isNaN(Number(x))、 Number.isNaN(x - 0)、そして Number.isNaN(Number(x)) は常に同じ値を返し、JavaScript では isNaN(x) がこれらの条件を表す最も短い形式となります。
例えばこの動作を使って、ある関数への引数が算術処理可能か(数値として利用できるか)どうかをテストするのに利用し、そうでない場合はデフォルト値などを与えるようにできます。この方法によりコンテキスト次第で値を暗黙的に変換する汎用性の高い JavaScript 関数を作成できます。
使用例
function increment(x) {
if (isNaN(x)) x = 0;
return x + 1;
};
// Number.isNaN() を使っても同じ効果が得られます:
function increment(x) {
if (Number.isNaN(Number(x))) x = 0;
return x + 1;
};
// 以下のケースで関数に渡される引数 x では
// isNaN(x) は常に false となるが、
// x は実際には数ではない。しかし算術式内で
// 使用が可能である
increment(""); // 1: "" は 0 に変換される
increment(new String()); // 1: 空文字列として表現される文字列オブジェクトは 0 に変換される
increment([]); // 1: [] は 0 に変換される
increment(new Array()); // 1: 空の配列として表現される配列オブジェクトは 0 に変換される
increment("0"); // 1: "0" は 0 に変換される
increment("1"); // 2: "1" は 1 に変換される
increment("0.1"); // 1.1: "0.1" は 0.1 に変換される
increment("Infinity"); // Infinity: "Infinity" は Infinity に変換される
increment(null); // 1: null は 0 に変換される
increment(false); // 1: false は 0 に変換される
increment(true); // 2: true は 1 に変換される
increment(new Date()); // 現在日時をミリ秒表現にした数値に 1 を加えたものが返される
// 以下のケースで関数に渡される引数 x では
// isNaN(x) は常に false となり、実際 x は数値である
increment(-1); // 0
increment(-0.1); // 0.9
increment(0); // 1
increment(1); // 2
increment(2); // 3
// そして……
increment(Infinity); // Infinity
// 以下のケースで関数に渡される引数 x では
// isNaN(x) は常に true となり、事実 x は数値ではない、
// そのため関数は引数を 0 に置き換え、結果 1 が返される
increment(String); // 1
increment(Array); // 1
increment("blabla"); // 1
increment("-blabla"); // 1
increment(0/0); // 1
increment("0/0"); // 1
increment(Infinity/Infinity); // 1
increment(NaN); // 1
increment(undefined); // 1
increment(); // 1
// isNaN(x) は常に isNaN(Number(x)) と同様ですが,
// x が存在していなければなりません!
isNaN(x) == isNaN(Number(x)) // x == undefined の場合も含め、x がいかなる値でも true が返される、
// なぜなら isNaN(undefined) == true かつ Number(undefined) は NaN を返す。
// しかし……
isNaN() == isNaN(Number()) // これは false となる、なぜなら isNaN() == true かつ Number() == 0
仕様
ブラウザ実装状況
| 機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| 基本サポート | (有) | (有) | (有) | (有) | (有) |
| 機能 | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
|---|---|---|---|---|---|---|
| 基本サポート | (有) | (有) | (有) | (有) | (有) | (有) |