MENU

JavaScript関数・メソッド用語解説

【JavaScript】 NaNって何だって話とisNaNについて

更新日:2021/09/28

 

JavaScriptには NaNという値があります。
数値に関する値のようですが、少しわかり難い面があります。

 

そこでここでは NaNについて少し掘り下げてみます。

 

NaNとは

 

NaNとはJavaScript固有のものではなくて、 IEEE 754 浮動小数点規格で制定されている値で、Not-a-Number を略したものです。

 

数値同士を想定した演算や、数値を引数として受け取り何らかの結果を返すメソッドなどで、『対象となる値が数値ではないから処理できなかったよ』という結果を表す値として使用することを想定しています。

 

結果が NaNになる例

 


console.log( parseInt( "abc") ); // NaN
console.log( 100 * "abc" );  // NaN

 

また、結果が数値であらわせないとき NaNを返すことも想定しています。
例えばMath.sqrt( )は、引数の平方根を返します。
引数に負数が指定されると、数値ではあらわせないため結果がNaNになります。

 

結果が数値であらわせないとき NaN

 


console.log( Math.sqrt( -1 ) ); // NaN

 

 

NaNは”数値ではない”という結果をあらわすため、他の値と比較するような性質のものではありません。
そのため、比較した際に内部でエラーを発生させるなどの処理が考えられますが、JavaScriptでは false を返します。

 

NaNとの比較は全てfalse

 


console.log( 1 === NaN ); // false
console.log( 100 > NaN ); // false
console.log( "abc" > NaN ); // false

 

最も注意すべき点は、NaN同士の比較も false になる点です。

 

NaN同士の比較も false

 


const nan1 = NaN;
const nan2 = NaN;

    // 変数の値は NaN
console.log( nan1 ); // NaN
console.log( nan2 ); // NaN

  // でも比較するとfalse
console.log( nan1 == nan2 );  // false
console.log( nan1 === nan2 ); // false

 

やってしまいがちなので、注意しましょう。

JavaScriptのNaNはグローバルオブジェクトのプロパティ値

 

NaN値は、グローバルオブジェクトのNaNプロパティが返す値です。

 

プログラムコードで入力された数値や文字列は、対応するデータ値(プリミティブ)に変換されます。

 

プリミティブへの変換

 


const num = 12345;  // ← 12345 という値の数値データに変換される
const text = "abcde"; // ← "abcde" という値の文字データに変換される

 

nullも同様に、null値に変換されます。

 

nullの変換

 


const nullValue = null;  // ← nullデータに変換される

 

しかし NaN は、グローバルオブジェクトのプロパティが参照されます。
次のコードの各行は、同じものを参照しています。

 

NaNの参照

 


const nan1 = NaN;
const nan2 = globalThis.NaN;

 

ただし前項でお伝えしたように、取得した値同士の比較は必ずfalseになるので、注意が必要です。

 

NaNの比較は必ずfalse

 


console.log( nan1 === nan2 ); // false
console.log( NaN === NaN ); // false
console.log( NaN === globalThis.NaN ); // false

 

また理論上は、NaNの値を変更できます。

 

理論上のNaN値変更

 


globalThis.NaN = "abcde";
const nan1 = NaN;
console.log( na1 );  // "abcde"

 

実際には上書き禁止になっているため、変更できません。
非strictモードは、そのまま処理が続行しますが、strictモードでは、変更時にエラーが発生します。

 

NaNは上書き禁止です

 


"use strict";
globalThis.NaN = "abcde";
 // TypeError: "NaN" is read-only

NaNの判定

 

結果がNaNかどうかを判定したいとき、次のコードのように直接 NaN と比較することができません。

 

NaNの判定(失敗)

 


const value = 123 * "abc";
console.log( value ); // NaN

if( value === NaN ){ // NaNとの比較結果は必ず false
   console.log( "結果がNaNです" );
}

 

値がNaNかどうかを確認するには、isNaNメソッドを使用します。

 

二つのisNaNメソッド

 

JavaScriptにはisNaNメソッドが二つ存在します。

 

一つがグローバルオブジェクトのメソッド。
もう一つが、Numberオブジェクトのメソッドです。

 

Numberオブジェクトもグローバルオブジェクトのプロパティなので、イメージ的には次のような関係になります。

 


グローバルオブジェクト
  ┃
  ┣ NaNプロパティ
  ┃
  ┣ isNaNメソッド
  ┃
  ┣ Numberオブジェクト
  ┃      ┣ isNaNメソッド
  ┃      ┃  

 

この二つのメソッドは、名前が同じですがチェックしている内容が異なります。
そのため、内容を理解して適切に使い分ける必要があります。

 

グローバルオブジェクトのisNaNメソッドは、NaN値かどうかのチェックに向いていません。
NaN値かどうかのチェックは、NumberオブジェクトのisNaNメソッドを使用します。

 

 

isNaNメソッド

 

グローバルオブジェクトのisNaNメソッドは、引数を一つ受け付けます。

 

こメソッドは、名前を見ると引数が NaN値かどうかを判定しているような印象を受けます。
実際は、NaNの元々の意味である、Not-a-Number、つまり数字として扱える値かどうかを判定しています。

 

JavaScriptでは四則演算などで、数値以外も数値としてみなすことがあります。

 

例えば、1 - truetrueが1とみなされて、結果は 0 です。

 

しかし、1 + "abc" の場合、"abc"を数値に変換できません。
数値と数値でないものを計算した結果は、”数値でないもの” すなわち NaN値 となります。

 

グローバルオブジェクトのisNaNメソッドは、"abc"のような数値に変換できない値のときtrueを返します。

 

数値としてみなされる値については、次の記事の最初の項目を読んでみてください。
【JavaScript】 数値チェック方法をケース別に解説します

 

isNaNによるNot-a-Number判定

 


console.log( isNaN( 12345 ) ); // false
console.log( isNaN( "12345" ) ); // false
console.log( isNaN( "abcde" ) ); // true
console.log( isNaN( true ) ); // false
console.log( isNaN( undefined ) ); // true
console.log( isNaN( null ) ); // false
console.log( isNaN( NaN ) ); // true
console.log( isNaN( Infinity ) ); // false
console.log( isNaN( {} ) ); // true

 

グローバルオブジェクトのisNaNメソッドは内部的には、最初に引数として受け取った値を数値に変換します。
このとき数値に変換できなかったものは、変換結果が NaN値 になり、isNaNの実行結果として true を返します。

 

引数と結果の関係を表にまとめると、次のようになります。

 

■isNaNの結果
値の型数値変換結果isNaN判定
Number有限値12341234false
InfinityInfinityInfinityfalse
NaNNaNNaNtrue
String数値文字列"1234"1234false
非数値文字列"abcde"NaNtrue
Nullnull0false
UndefinedundefinedNaNtrue
Booleantruetrue1false
falsefalse0false
SymbolSymbol()TypeError例外
BigInt100nTypeError例外
Object数値プリミティブに変換できるfalse
数値プリミティブに変換できないtrue

 

■数値プリミティブに変換できるオブジェクト
一般的なオブジェクトは数値プリミティブに変換できませんが、[Symbol.toPrimitive]プロパティを実装することで数値プリミティブに変換できるようになります。詳しくは次の記事をご覧ください。
【JavaScript】 オブジェクトで直接計算させるSymbol.toPrimitiveでプリミティブ変換

 

Number.isNaNメソッド

 

NumberオブジェクトのisNaNメソッドは、受け取った引数が NaN値のとき、trueを返します。

 

Number.isNaNによるNaN判定

 


console.log( Number.isNaN( 12345 ) ); // false
console.log( Number.isNaN( "12345" ) ); // false
console.log( Number.isNaN( "abcde" ) ); // false
console.log( Number.isNaN( true ) ); // false
console.log( Number.isNaN( undefined ) ); // false
console.log( Number.isNaN( null ) ); // false
console.log( Number.isNaN( NaN ) ); // true
console.log( Number.isNaN( Infinity ) ); // false
console.log( Number.isNaN( {} ) ); // false

 

演算子による演算結果や関数の実行結果が NaNかどうかを確認する場合、Number.isNaNを使用します。

 

演算結果等が NaNかどうかのチェック

 


const checkNaN = value =>
    console.log( Number.isNaN( value ) ? "NaNです" : "NaNではない" );

const value1 = 100 * 100;
const value2 = 100 * "abcde";

checkNaN( value1 );
checkNaN( value2 );

const intVal = parseInt( "abcdefg" );
checkNaN( intVal );

 

比較による NaN判定

 

NaN値は、自分自身を比較しても false になるという奇妙な性質があります。
その特徴を活かして、次のように比較することで NaN かどうかを確認できます。

 

NaNの判定

 

const value = 123 * "abc";

if( value !== value ){
   console.log( "結果がNaNです" );
}

 

この項の最初の例では、等価比較( === )をおこなっていました。
ここでは、不等価比較( !== )をおこなっています。

 

NaN以外の値は自分自身を比較するとtrueになるので、このようなチェック方法も有効です。

 

しかし今後のECMAScriptの改版で、同じ性質を持つ値が追加される可能性はゼロではありません。
それ以前に、演算の目的がわかり難く、コメント必須です。

 

何らかの理由がないなら、Number.isNaNを使用することをおススメします。

けーちゃんおススメJavaScript入門書

  • スラスラ読める JavaScript ふりがなプログラミング
  • プログラム未経験者がJavaScript始めるならコレ!
    コードを掲載して自分で理解しろという投げっぱなしな入門書とは異なり、コードに一つ一つどんなことをやっているかをふりがなという形式で解説しています。
    それでいてJavaScriptの基礎と応用を学べる良書です。
  • これからWebをはじめる人のHTML&CSS、JavaScriptのきほんのきほん
  • JavaScriptの機能を実践で活かすにはHTMLやCSSの知識が不可欠です。
    しかしそれらの知識があることが前提として書かれている書籍が多い中、この本は総合的な知識を身に着けることができます。
    HTMLやCSSの知識も不安な方には、ぴったりの一冊です
  •  

    入門書の役割は、自分のやりたいことをネットで調べることができるようになるための、基礎的な知識の獲得です。
    まずはこれらの本でしっかりと基礎知識を身につけましょう。
    そしてもっと高度なことや専門的なことはネットで調べ、情報が足りないと感じたら書籍を購入してください。


    記事の内容について

     

    こんにちはけーちゃんです。
    説明するのって難しいですね。


    「なんか言ってることおかしくない?」
    たぶん、こんなご意見あると思います。

    裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

    そんなときは、ご意見もらえたら嬉しいです。

    ご意見はこちら。
    https://note.affi-sapo-sv.com/info.php

    【お願い】

    お願い

    ■このページのURL


    ■このページのタイトル


    ■リンクタグ


    ※リンクして頂いた方でご希望者には貴サイトの紹介記事を作成してリンクを設置します。
    サイト上部の問い合わせよりご連絡ください。
    ただしサイトのジャンルによっては、お断りさせていただくことがあります。