JavaScript/Number/isNaN

カテゴリ:Book:JavaScript#Number/isNaN%20

Number.isNaN() は、ECMAScript における Number オブジェクトのメソッドで、渡された値が NaN(Not a Number)かどうかを判定します。このメソッドは、グローバルの isNaN() 関数とは異なり、数値以外の値を数値に変換せずに判定を行います[1]

構文

Number.isNaN(value)

パラメータ

  • value: 検査する値。

戻り値

指定された値が NaN であれば true、そうでなければ false を返します。

特性

Number.isNaN() には、以下のような特性があります:

  • 静的メソッド: このメソッドは Number コンストラクタに属し、Number インスタンスからは直接呼び出せません。
  • 厳密な NaN チェック: グローバルの isNaN() 関数とは異なり、Number.isNaN() は引数を数値に変換しようとしません。
  • 型チェック: 引数が数値型でなく NaN でもない場合は false を返します。
  • ECMAScript 6: このメソッドは ECMAScript 6(ES2015)で導入されました。

基本的な使用法

以下のプログラムは、Number.isNaN() の基本的な使用法を示しています。

// NaN の判定
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(Number.NaN)); // true
console.log(Number.isNaN(0 / 0)); // true

// 数値(NaN 以外)の判定
console.log(Number.isNaN(42)); // false
console.log(Number.isNaN(-3.14)); // false
console.log(Number.isNaN(Infinity)); // false

// 数値でない値の判定
console.log(Number.isNaN('NaN')); // false
console.log(Number.isNaN(undefined)); // false
console.log(Number.isNaN({})); // false
console.log(Number.isNaN('blabla')); // false

このプログラムでは、Number.isNaN() が NaN 値に対してのみ true を返し、数値型でない値や NaN 以外の数値に対しては false を返すことを示しています。

グローバルの isNaN() との違い

以下のプログラムは、Number.isNaN() と グローバルの isNaN() 関数の違いを示しています。

// Number.isNaN() vs グローバルの isNaN()
console.log(Number.isNaN('NaN')); // false (文字列は数値型ではないため)
console.log(isNaN('NaN')); // true (文字列を数値に変換しようとして NaN になる)

console.log(Number.isNaN('123')); // false (文字列は数値型ではないため)
console.log(isNaN('123')); // false (文字列を数値に変換すると 123 になる)

console.log(Number.isNaN(undefined)); // false (undefined は数値型ではないため)
console.log(isNaN(undefined)); // true (undefined を数値に変換しようとして NaN になる)

console.log(Number.isNaN({})); // false (オブジェクトは数値型ではないため)
console.log(isNaN({})); // true (オブジェクトを数値に変換しようとして NaN になる)

console.log(Number.isNaN(NaN)); // true
console.log(isNaN(NaN)); // true

このプログラムでは、Number.isNaN() とグローバルの isNaN() 関数の主な違いを示しています。グローバルの isNaN() 関数は引数を数値に変換しようとするため、変換の結果 NaN になる値(数値ではない文字列や undefined、オブジェクトなど)に対しても true を返します。一方、Number.isNaN() は厳密に NaN 値のみを判定します。

Number.isNaN() のポリフィル

以下のプログラムは、Number.isNaN() のポリフィル(古いブラウザで実装するためのコード)を示しています。

// Number.isNaN() のポリフィル
if (!Number.isNaN) {
  Number.isNaN = function(value) {
    // NaN は自分自身と等しくない唯一の JavaScript の値
    return typeof value === 'number' && value !== value;
  };
}

// テスト
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN('NaN')); // false

このプログラムでは、Number.isNaN() が存在しない環境でこのメソッドを実装するポリフィルを示しています。ポリフィルでは、値が数値型であることを確認した上で、その値が NaN かどうかをチェックします。

実用的な例

数値計算の結果の検証

以下のプログラムは、数値計算の結果を検証する例を示しています。

// 数値計算の結果を検証する関数
function validateCalculation(input1, input2, operation) {
  // 入力値を数値に変換
  const num1 = Number(input1);
  const num2 = Number(input2);
  
  // 入力値が有効な数値かをチェック
  if (Number.isNaN(num1) || Number.isNaN(num2)) {
    return { valid: false, error: '無効な入力値です' };
  }
  
  // 計算を実行
  let result;
  switch (operation) {
    case 'add':
      result = num1 + num2;
      break;
    case 'subtract':
      result = num1 - num2;
      break;
    case 'multiply':
      result = num1 * num2;
      break;
    case 'divide':
      // ゼロ除算をチェック
      if (num2 === 0) {
        return { valid: false, error: 'ゼロで除算できません' };
      }
      result = num1 / num2;
      break;
    default:
      return { valid: false, error: '未対応の操作です' };
  }
  
  // 結果が NaN かをチェック
  if (Number.isNaN(result)) {
    return { valid: false, error: '計算結果が無効です' };
  }
  
  return { valid: true, result };
}

// 有効な計算
console.log(validateCalculation('10', '5', 'add')); // { valid: true, result: 15 }
console.log(validateCalculation(10, 0, 'multiply')); // { valid: true, result: 0 }

// 無効な入力
console.log(validateCalculation('abc', '5', 'add')); // { valid: false, error: '無効な入力値です' }

// ゼロ除算
console.log(validateCalculation(10, 0, 'divide')); // { valid: false, error: 'ゼロで除算できません' }

このプログラムでは、ユーザー入力やその他のソースからの値を使用して数値計算を行う前に、これらの値が有効な数値かどうかを Number.isNaN() を使用してチェックする例を示しています。また、計算結果が NaN にならないかもチェックしています。

フォーム入力の検証

以下のプログラムは、フォーム入力を検証する例を示しています。

// フォーム入力を検証するクラス
class FormValidator {
  constructor() {
    this.errors = [];
  }
  
  // 数値入力の検証
  validateNumberInput(value, fieldName, options = {}) {
    // 空の入力をチェック
    if (value === '' && !options.allowEmpty) {
      this.errors.push(<code>${fieldName} は必須です</code>);
      return false;
    }
    
    // 空を許可する場合
    if (value === '' && options.allowEmpty) {
      return true;
    }
    
    // 数値への変換
    const num = Number(value);
    
    // NaN をチェック
    if (Number.isNaN(num)) {
      this.errors.push(<code>${fieldName} は有効な数値ではありません</code>);
      return false;
    }
    
    // 最小値をチェック
    if (options.min !== undefined && num < options.min) {
      this.errors.push(<code>${fieldName}  ${options.min} 以上である必要があります</code>);
      return false;
    }
    
    // 最大値をチェック
    if (options.max !== undefined && num > options.max) {
      this.errors.push(<code>${fieldName}  ${options.max} 以下である必要があります</code>);
      return false;
    }
    
    // 整数値をチェック
    if (options.integer && !Number.isInteger(num)) {
      this.errors.push(<code>${fieldName} は整数である必要があります</code>);
      return false;
    }
    
    return true;
  }
  
  // エラーの取得
  getErrors() {
    return this.errors;
  }
  
  // 検証のリセット
  reset() {
    this.errors = [];
  }
}

// 使用例
const validator = new FormValidator();

// 年齢のバリデーション
validator.validateNumberInput('25', '年齢', { min: 18, max: 120, integer: true });
validator.validateNumberInput('abc', '年齢', { min: 18, max: 120, integer: true });
validator.validateNumberInput('17', '年齢', { min: 18, max: 120, integer: true });
validator.validateNumberInput('18.5', '年齢', { min: 18, max: 120, integer: true });

console.log(validator.getErrors());
// [
//   "年齢 は有効な数値ではありません",
//   "年齢 は 18 以上である必要があります",
//   "年齢 は整数である必要があります"
// ]

このプログラムでは、フォーム入力の検証を行うクラスを示しています。Number.isNaN() を使用して、入力が有効な数値かどうかをチェックしています。また、最小値や最大値、整数であることなど、追加の制約も検証しています。

NaN 値の検出と処理

以下のプログラムは、配列内の NaN 値を検出して処理する例を示しています。

// 配列内の NaN 値を検出して処理する関数
function handleNaNValues(arr, replacementValue = 0) {
  // NaN 値のインデックスを取得
  const nanIndices = arr
    .map((value, index) => Number.isNaN(value) ? index : -1)
    .filter(index => index !== -1);
  
  // NaN を置換した新しい配列を作成
  const cleanArray = [...arr];
  nanIndices.forEach(index => {
    cleanArray[index] = replacementValue;
  });
  
  return {
    originalArray: arr,
    cleanArray,
    nanCount: nanIndices.length,
    nanIndices
  };
}

// 使用例
const dataArray = [1, 2, NaN, 4, NaN, 6, 7];
const result = handleNaNValues(dataArray);

console.log(result.originalArray); // [1, 2, NaN, 4, NaN, 6, 7]
console.log(result.cleanArray); // [1, 2, 0, 4, 0, 6, 7]
console.log(result.nanCount); // 2
console.log(result.nanIndices); // [2, 4]

// カスタム置換値を使用
const customResult = handleNaNValues(dataArray, -1);
console.log(customResult.cleanArray); // [1, 2, -1, 4, -1, 6, 7]

このプログラムでは、配列内の NaN 値を検出し、指定された値で置換する関数の例を示しています。Number.isNaN() を使用して NaN 値を正確に識別し、それらのインデックスを取得します。

Number.isNaN() と isNaN() の比較

Number.isNaN() とグローバルの isNaN() 関数は以下の点で異なります:

  • 型変換: グローバルの isNaN() 関数は引数を数値に変換しようとしますが、Number.isNaN() はそのような変換を行いません。
  • 厳密さ: Number.isNaN() は厳密に NaN 値のみを判定し、数値型でない値に対しては常に false を返します。
  • 一貫性: Number.isNaN() はより一貫した結果を提供し、予測がしやすいです。
  • 推奨: 最新の JavaScript コードでは、より厳密な Number.isNaN() の使用が推奨されています。
// 比較の例
const values = [
  NaN,          // 本物の NaN
  'NaN',        // 文字列の "NaN"
  undefined,    // undefined
  {},           // 空のオブジェクト
  '123',        // 数値に変換可能な文字列
  'hello',      // 数値に変換できない文字列
  Infinity      // 無限大
];

console.log('Number.isNaN() の結果:');
values.forEach(val => {
  console.log(<code>${String(val)}: ${Number.isNaN(val)}</code>);
});

console.log('\nisNaN() の結果:');
values.forEach(val => {
  console.log(<code>${String(val)}: ${isNaN(val)}</code>);
});

/* 出力:
Number.isNaN() の結果:
NaN: true
NaN: false
undefined: false
[object Object]: false
123: false
hello: false
Infinity: false

isNaN() の結果:
NaN: true
undefined: true
[object Object]: true
123: false
hello: true
Infinity: false
*/

このプログラムでは、様々な値に対する Number.isNaN() とグローバルの isNaN() 関数の結果を比較しています。グローバルの isNaN() 関数は数値に変換できない値に対して true を返しますが、Number.isNaN() は実際の NaN 値に対してのみ true を返します。

その他の Number オブジェクトのメソッド

ECMAScript は、Number オブジェクトに他の便利なメソッドも定義しています:

脚註

  1. Number.isNaN() はより厳密な NaN チェックを提供し、数値型でない値に対しては常に false を返します。

外部リンク

カテゴリ:Book:JavaScript#Number/isNaN%20 カテゴリ:JavaScript
カテゴリ:Book:JavaScript カテゴリ:JavaScript カテゴリ:Pages using the JsonConfig extension