このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。

View in English Always switch to English

NaN

Baseline 広く利用可能

この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2015年7月以降、すべてのブラウザーで利用可能です。

NaN はグローバルプロパティで、非数 (Not-A-Number) を表す値です。

試してみましょう

function sanitize(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

console.log(sanitize("1"));
// 予想される結果: "1"

console.log(sanitize("NotANumber"));
// 予想される結果: NaN

Number.NaN と同じ数値です。

NaN のプロパティ属性
書込可能不可
列挙可能不可
設定可能不可

解説

NaN はグローバルオブジェクトのプロパティです。言い換えれば、グローバルスコープにある変数です。

最近のブラウザーでは、NaN は構成不可かつ書き込み不可のプロパティです。そうでない場合でも、これを上書きすることは避けてください。

NaN を返す演算には 5 種類があります。

  • 数値への変換に失敗した(parseInt("blabla")Number(undefined) 等の明示的なもの、Math.abs(undefined) のような暗黙的なもの)
  • 結果が実数値にならない算術演算(Math.sqrt(-1) など)
  • 不確定形(0 * Infinity1 ** InfinityInfinity / InfinityInfinity - Infinity、など)
  • オペランドが NaN である、または NaN を取得するメソッドや式(7 ** NaN7 * "blabla" など。このことは NaN が伝染性を持つことを意味します。
  • 不正な値を数値として表す必要があるその他の場合(不正な Date である new Date("blabla").getTime()"".charCodeAt(1) など)

NaN とその挙動は JavaScript が発明したものではありません。浮動小数点演算におけるその意味づけ(NaN !== NaN を含む)は IEEE 754 によって指定されています。NaN の挙動には以下が含まれます。

  • 数学演算(ただしビット演算を除く)においてNaNが関与する場合、結果は通常NaNとなります。(下記の反例を参照してください。)
  • 関係演算子(><>=<=)のいずれかのオペランドが NaN の場合、結果は常に false となります。
  • NaN は、他の値(別の NaN 値を含む)とは等しくない(==!====!==)を含む他のいかなる値とも等しくない。

NaN は JavaScript で偽値の値の一つと同時にあります。

NaN に対する検査

ある値が NaN かどうかを判断するには、Number.isNaN() または isNaN() を使用すると最も明確に判定できます。あるいは、NaN は自身と等しくない唯一の値であるため、x !== x のような自己比較で検査することも可能です。

js
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true
Number.isNaN(NaN); // true

function valueIsNaN(v) {
  return v !== v;
}
valueIsNaN(1); // false
valueIsNaN(NaN); // true
valueIsNaN(Number.NaN); // true

ただし、 isNaN()Number.isNaN() には違いがあることに気をつけてください。前者は、値そのものが NaN であったり、値の変換の結果 NaN になる場合に true を返します。後者は値そのものが NaN のときにだけ true を返します。

js
isNaN("hello world"); // true
Number.isNaN("hello world"); // false

同じ理由で、長整数値の場合は isNaN() ではエラーが発生しますが、 Number.isNaN() では発生しません。

js
isNaN(1n); // TypeError: Conversion from 'BigInt' to 'number' is not allowed.
Number.isNaN(1n); // false

さらに、配列メソッドの中には NaN を探せないものもあれば、探せるものもあります。具体的には、インデックス検索メソッド(indexOf()lastIndexOf())は NaN を探すことはできませんが、値検索メソッド(includes())は探すことができます。

js
const arr = [2, 4, NaN, 12];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true

// 適切に定義された述語を受け入れるメソッドは常に NaN を探すことができる
arr.findIndex((n) => Number.isNaN(n)); // 2

NaN とその比較について詳しくは、等価性の比較と同一性を参照してください。

明確に識別可能な NaN 値

2 つの浮動小数点数が異なる二進表現を持ちながらも両方とも NaN となる可能性があります。これは IEEE 754 エンコード方式において、指数が 0x7ff で仮数部が0でない浮動小数点数はすべて NaN となるためです。JavaScript で、型付き配列を使用してビット単位の操作を行うことができます。

js
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);
const b2f = (x) => new Float64Array(x.buffer)[0];
// NaN のバイト表現の取得
const n = f2b(NaN);
const m = f2b(NaN);
// 符号ビットを変更する(NaN には影響しない)
n[7] += 2 ** 7;
// n[0] += 2**7; ビッグエンディアンの処理系のため
const nan2 = b2f(n);
console.log(nan2); // NaN
console.log(Object.is(nan2, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan2)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 255]
// まず最初のビットを変更する。これは仮数の最下位ビットであり、NaN には影響しない。
m[0] = 1;
// m[7] = 1; ビッグエンディアンの処理系のため
const nan3 = b2f(m);
console.log(nan3); // NaN
console.log(Object.is(nan3, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan3)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127]

暗黙に NaN をエスケープ

NaN は数学演算を通じて伝播するため、通常は計算の最後に一度 NaN を検査するだけでエラー状態を検出できます。NaN が黙って無視される唯一の場合は、指数が 0べき乗を使用する場合であり、この場合基数の値を検査せずに即座に 1 を返します。

js
NaN ** 0 === 1; // true

仕様書

仕様書
ECMAScript® 2027 Language Specification
# sec-value-properties-of-the-global-object-nan

ブラウザーの互換性

関連情報