JSではなぜisNaN(null)== falseなのですか?


128

JSのこのコードは、「nullは数値だと思います」というポップアップを表示します。何が欠けていますか?

if (isNaN(null)) {
  alert("null is not a number");
} else {
  alert("i think null is a number");
}

Firefox 3を使用しています。これはブラウザのバグですか?

その他のテスト:

console.log(null == NaN);   // false
console.log(isNaN("text")); // true
console.log(NaN == "text"); // false

それで、問題はNaNとの正確な比較ではないようです?

編集:これで質問に回答しました。投稿をクリーンアップして、アーカイブに適したバージョンを用意しました。ただし、これにより、一部のコメントや一部の回答でさえも少しわかりにくくなります。著者を責めないでください。私が変更したものの中には:

  • そもそも意味を元に戻すことで見出しをめちゃくちゃにしたというメモを削除
  • 以前の回答では、動作がおかしいと思う理由を明確に述べていなかったため、文字列をチェックして手動で比較する例を追加しました。

3
「isNaN(null)== falseなのはなぜですか」という意味ですか?
Matt Rogish

コードに基づいて、isnan(null)は、「nullは数値だと思います」と表示された場合、falseを返します(nullは「数値ではありません」ではありません)。
devinmoore 2008

回答:


114

コードは「x数値ですか?」と質問しようとしていると思います。ここの特定のケースでx = null。関数isNaN()はこの質問に答えるために使用できますが、意味的には値を具体的に参照していますNaN。ウィキペディアからNaN

NaN(N ot a N umber)は、特に浮動小数点計算で、未定義または表現できない値を表す数値データ型の値です。

ほとんどの場合、「数値はnullですか?」いいえにする必要があります。ただし、isNaN(null) == falsenullでないため、意味的に正しいNaNです。

アルゴリズムの説明は次のとおりです。

この関数isNaN(x)は、渡されたパラメータを数値1(と同等Number(x))に変換し、値がかどうかをテストしますNaN。パラメータを数値に変換できない場合は、2Number(x)を返します。したがって、パラメータから数値への変換の結果がの場合、trueを返します。それ以外の場合は、falseを返します。NaNxNaN

したがって、特定のケースx = nullnullは、は数値0に変換され(評価Number(null)してみて0を返すことを確認してください)、isNaN(0)false を返します。数字のみの文字列は数値に変換でき、isNaNもfalseを返します。'abcd'数値に変換できない文字列(など)はisNaN('abcd')、特にをNumber('abcd')返すため、trueを返しますNaN

これらの明らかなエッジケースに加えて、0/0のようなNaNを返す標準的な数値の理由があります。

質問に示されている一見一貫性のない等価性テストに関しては、の動作は、それ自体を含む他のオペランドに関係なく、NaNすべての比較x == NaNが偽になるように指定されています1NaN


8
ところで、NaN !== NaN。だから、と言ってNumber('abcd') == NaNいるのNumber('abcd')は完全に正しいとは言えNaNませんNaN。私はJavaScriptが大好きです。
nilfalse 2013

はい。私はそれを伝えるつもりでしたが、私Number('abcd')NaNそれが等しいかどうか真にテストすることをほのめかしました、そうではありません。編集します。
Glenn Moss

されている理由だろうかisNaNNumber、そのように動作するように設計されましたか?
timidboy 2014

1
変換null0のみ(この文脈では少なくとも)内で発生isNaN()その引数を強制変換機能、。
Glenn Moss

3
Number(null)== 0 but parseInt(null)== NaN love JS
JoshBerke

31

私はこの問題に自分で遭遇しました。

私にとって、isNaNを使用する最良の方法はそうです

isNaN(parseInt(myInt))

上からフィゾームの例をとると、

var x = [undefined, NaN,     'blah', 0/0,  null, 0,     '0',   1,     1/0, -1/0,  Number(5)]
x.map( function(n){ return isNaN(parseInt(n))})
        [true,      true,    true,   true, true, false, false, false, true, true, false]

(入力に従って結果を調整しました。読みやすくなることを願っています。)

これは私には良いようです。


1
myInt= "123d"の場合は機能しません。parseInt「123d」を123に変換し、isNaNテストに失敗します。
divesh premdeep 2015

確かに、もしあなたがそのシナリオを捕らえたければ、私の答えとグレンのシナリオを組み合わせることをお勧めします。これは次のようになりますisNaN(parseInt(str,10)) || isNaN(Number())。btw-私にとってparseIntは、文字列の数値を使用するために実行する必要があるため、「123d」を有効な数値と見なすことは問題ありません。ただし、そのシナリオも検出する必要があると思います。
モグラビ男2015

8

(私のもう1つのコメントは実際的なアプローチをとっています。これが理論的な側面です。)

Javascriptが実装しているECMA 262標準を調べました。isNanの仕様:

ToNumberを引数に適用し、結果がNaNの場合はtrueを返し、それ以外の場合はfalseを返します。

セクション9.3は、ToNumber(呼び出し可能な関数ではなく、型変換システムのコンポーネント)の動作を指定しています。表を要約すると、特定の入力タイプはNaNを生成できます。これらは、type undefined、type number(値のみNaN)、プリミティブ表現がNaNであるオブジェクト、およびstring解析できないオブジェクトです。これは、葉undefinedNaNnew Number(NaN)、およびほとんどの文字列。

NaNに渡されたときに出力として生成されるそのような入力はToNumbertrueに供給されたときにを生成しisNaNます。以来null缶が正常に数値に変換され、それが生成されませんtrue

そしてそれが理由です。


7

これは確かに不安です。これが私がテストした値の配列です:

var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]

(Firebugコンソールで)次のように評価されます。

,NaN,blah,NaN,,0,0,1,Infinity,-Infinity,5

x.map(isNaN)(各値でisNaN を呼び出すために)を呼び出すと、次のようになります。

true,true,true,true,false,false,false,false,false,false,false

結論として、isNaNかなり役に立たないように見えます!(編集:isNaNがNumberに対してのみ定義されていることが判明した場合を除いて、その場合、それはうまく機能します-紛らわしい名前でのみです)。

ちなみに、これらの値のタイプは次のとおりです。

x.map(function(n){return typeof n})
-> undefined,number,string,number,object,number,string,number,number,number,number

NaNはどういう意味だと思いますか?NaNについて、またはそのテストにおいて、何が誤解を招くと思いますか?なぜあなたは邪魔されていますか?
Bekim Bacaj 2017年

さて、これは8年前ですが、1)Number型ではない値に対して一貫性のない結果があり、2)Number型ではないものに対してtrueを返すことが、私には不安であったようです。文字列は実際にはNaNではないためです。(また、これが発生する理由を説明している他の私の回答も参照してください。)
MODをうまく処理する

5

NullはNaNではなく、文字列もNaNではありません。isNaN()は、本当にNaNオブジェクトがあるかどうかをテストします。


ただし、isNaN( "text")がtrueを返すため、少なくとも文字列がNaNオブジェクトにキャストされます。
Hanno Fietz

1

JSに関しては正確にはわかりませんが、他の言語でも同様のことがわかりました。これは通常、関数がnullがNaNと正確に等しいかどうかのみをチェックしているためです(つまり、null === NaNはfalseになります)。つまり、nullは実際には数値であると考えているのではなく、nullがNaNではないということです。これはおそらく、両方がJSで異なるように表現されているため、9!== '9'と同じように、それらが正確に等しくなることはないためです。


1

ES5ではisNaN (number)、引数がNaNに強制変換される場合はtrue を返し、それ以外の場合はfalse を返すように定義されています。

  • 場合はToNumber(数)が NaNである、trueを返します。
  • それ以外の場合は、falseを返します。

また、抽象演算ToNumber変換テーブルを参照してください。したがって、内部的にjsエンジンの評価ToNumber(Null)+0であり、最終的にisNaN(null)false


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.