isNaN(“”)(スペースを含む文字列)がfalseに等しいのはなぜですか?


160

JavaScriptでは、なぜはにisNaN(" ")評価されますfalseが、にisNaN(" x")評価されtrueますか?

私は、テキスト入力フィールドに数値演算を実行しています、と私はフィールドがあるかどうかをチェックしていますnull""またはNaN。誰かがフィールドにいくつかのスペースを入力すると、3つすべての検証が失敗し、なぜisNaNチェックを通過しないのか混乱します。


1
うーん...対象の残りの半分がどこに行ったのかよくわかりません。「JavaScript:isNaN( "")がfalseと評価されるのはなぜですか?」
IVRアベンジャー、

Jes、それは動作です(isNaNの場合、空またはスペースはfalseを返します)が、この関数の正確な仕様は見つかりませんでした。
Lucero、

これに答える質問があります:http
Lucero

これらの問題のJavascriptはブードゥー教のようです!あなたは決して知りませんし、説明は常に非常に複雑です。"" == false // trueおよびisNaN(" ") // false
ジョアンピメンテルフェレイラ

回答:


155

JavaScriptは空の文字列を0と解釈し、isNANテストに失敗します。空の文字列を0に変換しない文字列でparseIntを最初に使用できます。結果はisNANで失敗します。


53
しかし、parseInt( "123abcd")は123を返します。つまり、isNaN(parseInt( "123abcd"))はfalseを返しますが、trueを返します。
Pawan Nogariya、

11
では、(IsNaN(string)|| isNaN(parseInt(string)))についてはどうですか
matt

5
の解釈には2つのステップがありますisNaN(arg)。1)argを数値に変換します。2)その数値が数値であるかどうかを確認しますNaN。それは私がそれをよりよく理解するのに役立ちました。
xdhmoore 2014

3
@Antonio_Haleyちょっと待ってください、わかりません。「JavaScriptが空の文字列を0と解釈する場合、parseInt( "")がNaNを返すのはなぜですか?
ジャン=フランソワ・ビーチャム

1
@Jean-Françoisそうですね、より正確なステートメントは、JavaScript自体ではなく、「isNaNは空の文字列を0として解釈する」です。
Antonio Haley、

82

これは驚くべきことかもしれませんが、そうでないかもしれませんが、JavaScriptエンジンの奇抜さを示すためのテストコードを次に示します。

document.write(isNaN("")) // false
document.write(isNaN(" "))  // false
document.write(isNaN(0))  // false
document.write(isNaN(null)) // false
document.write(isNaN(false))  // false
document.write("" == false)  // true
document.write("" == 0)  // true
document.write(" " == 0)  // true
document.write(" " == false)  // true
document.write(0 == false) // true
document.write(" " == "") // false

つまり、これは

" " == 0 == false

そして

"" == 0 == false

だが

"" != " "

楽しんで :)


5
+1素晴らしい投稿。トリプルが等しい(===および!==)演算子がここにどのように適合するかを追加できますか?
ベンドウェイ2009

2
NaN === NaNまたはNaN == NaN ;-)を試してみてください。これはすべて、JavaScriptエンジンが奇抜であるか、またはそのJavaScriptが奇抜なプログラマにとって悪いのかを知りません。
KooiInc 2009

10
@Kooilnc NaN!= NaNは、実際には一度の選択に適しているという事実。NaNは、ほとんどの場合、プログラマーの意図とは異なる計算の結果であり、「間違った」2つの計算の結果が等しいと仮定するのはかなり危険だと私は言います。
skrebbel、2011年

2
@Kooilncはjavascriptの奇妙さから少しも奪わないようにすべきですが、これらのNaNはIEEE 754浮動小数点標準に従っているだけです。ビッグW:en.wikipedia.org/wiki/NaN
Spike0xff

@NickBerardi F'ing LOL!私はこの投稿を見てうれしいです。isNaN関数が非常に遅延している理由を理解するのに役立ちました。私は今、完全には開発されていないコードからそれを取り除き、おそらく再び使用することはないでしょう。私はのために検証しますnull""" "自分自身。ありがとう!
VoidKing 2013年

16

よりよく理解するには、43ページの「文字型に適用されるToNumber」のEcma-Script spec pdfを開いてください。

文字列に数値構文があり、空白文字をいくつでも含めることができる場合は、数値型に変換できます。空の文字列は0と評価されます。また、文字列「Infinity」は

isNaN('Infinity'); // false

13

使ってみてください:

alert(isNaN(parseInt("   ")));

または

alert(isNaN(parseFloat("    ")));

3
こんにちは、isNaN(parseInt( "123a")):123が返されるため、文字列に数値の数値が含まれている場合、解決策は機能しません
Sajjad Ali Khan


5

私はそれがJavascriptの型付けのためだと思います:' 'はゼロに変換されますが、そうで'x'はありません:

alert(' ' * 1); // 0
alert('x' * 1); // NaN

4

正確なisNumber関数を実装したい場合は、Javascriptからそれを行う1つの方法を次に示します。

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}

4
@Xyanこの場合、この関数は、OPが要求するタスクを実行するのにあまり役立ちません。これは、数値の文字列表現を検査することでした...
ErikE

「数値」などの文字列リテラルに対して任意の値のいわゆる厳密な等価演算子を使用するのは愚かです
Bekim Bacaj

4

完全に正しくない回答

アントニオヘイリーの非常に支持され、受け入れられている答えは、このプロセスがJavaScriptのparseInt関数を通過すると誤った仮定をしています。

文字列でparseIntを使用できます...結果は失敗するはずですisNAN。

このステートメントは、次の文字列で簡単に反証できます"123abc"

parseInt("123abc")    // 123     (a number...
isNaN("123abc")       // true     ...which is not a number)

これにより、JavaScriptのparseInt関数が"123abc"数値として返されることがわかりますが、123そのisNaN関数はそれ"123abc" 数値ではないことを示しています。

正解

ECMAScript-262はisNaNセクション18.2.3でチェックの動作を定義しています。

18.2.3 isNaN(数)

isNaN関数である%isNaN%固有のオブジェクト。ときにisNaN機能を1つの引数の数と呼ばれ、次のステップが取られます:

  1. するnumことができますか?ToNumber(number)
  2. 場合numNaN、戻りますtrue
  3. それ以外の場合は、を返しfalseます。

ToNumberそれが参照する機能もで定義されているのECMAScript-262のセクション7.1.3。ここでは、JavaScriptがこの関数に渡される文字列をどのように処理するかを説明します。

質問の最初の例は、空白文字のみを含む文字列です。このセクションでは、次のように述べています。

A StringNumericLiteral空であるか、空白しか含まに変換されます+0

" "例列は、従ってに変換される+0番号です。

同じセクションにも次のように記載されています。

文法がStringをの展開として解釈できない場合、StringNumericLiteral結果はToNumberですNaN

そのセクションに含まれるすべてのチェックを引用しない" x"と、質問の例はとして解釈できないため、上記の条件に該当しStringNumericLiteralます。" x"したがって、に変換されNaNます。


2

理由はわかりませんが、問題を回避するために、チェックする前にいつでも空白を削除できます。とにかくそれをしたいでしょう。


4
トリミングされた空の文字列もisNaNテストに失敗します。
Egemenk 2014

2

関数isNaN("")文字列から数値への型強制実行します

ECMAScript 3-5では、typeof演算子の次の戻り値を定義しています。

  • 未定義
  • オブジェクト(null、オブジェクト、配列)
  • ブール
  • ストリング
  • 関数

テストを関数本体でラップする方が良い:

function isNumber (s) {
    return typeof s == 'number'? true
           : typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
           : (typeof s).match(/object|function/)? false
           : !isNaN(s)
}

この関数は変数のをテストするためのものではなく、強制された値をテストします。たとえば、ブール値と文字列は数値に強制変換されるため、この関数を次のように呼び出すことができます。isNumberCoerced()

stringnumber以外のタイプをテストする必要がない場合は、次のスニペットを条件の一部として使用できます。

if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
    alert("s is a number")

1

整数であるかどうかを適切にチェックしたい場合は、次の関数を使用することをお勧めします。

function isInteger(s)
{
   return Math.ceil(s) == Math.floor(s);
}

1

これisNaN(" ")はfalseでありisNaN、非数値を数値型に強制変換するため、グローバル関数の混乱する動作の一部です。

MDNから

isNaN関数仕様の非常に初期のバージョンから、非数値引数に対するその動作は混乱を招きました。isNaN関数の引数の型がNumberでない場合、値は最初にNumberに強制変換されます。次に、結果の値をテストして、それがであるかどうかを判断しますNaN。したがって、数値型に強制変換されたときに有効な非NaN数値(特に空の文字列とブールプリミティブ、強制的に数値に0または1を与える)になる非数値の場合、「false」の戻り値は予期しないものになる可能性があります。たとえば、空の文字列は確かに「数字ではありません」です。

また、ECMAScript 6にはNumber.isNaN、MDNによると、メソッドも存在することに注意してください。

グローバルisNaN()関数と比較してNumber.isNaN()、パラメーターを数値に強制的に変換する問題が発生しません。つまり、通常はに変換される値を渡しても安全ですNaNが、実際にはと同じ値ではありませんNaN。これは、型番号の値のみがNaN返されることも意味しますtrue

残念ながら

Number.isNaNブログの投稿「醜いJavaScriptとES6 NaNの問題の修正」で概説されているように、ECMAScript 6の方法にも独自の問題があります。


1

isNaN(あなたのケースでは、文字列)他のタイプの引数は数値に変換されますので、この関数は、引数として数値を期待する前に、実際の関数のロジックが実行されます。(これNaNもNumber型の値であることに注意してください!)

ところで これはすべての組み込み関数に共通です。特定の型の引数が必要な場合、実際の引数は標準の変換関数を使用して変換されます。すべての基本型(ブール、文字列、数値、オブジェクト、日付、null、未定義)の間には標準の変換があります。

Stringto の標準変換は、でNumber明示的に呼び出すことができますNumber()。だから私たちはそれを見ることができます:

  • Number(" ") 評価する 0
  • Number(" x") 評価する NaN

これを考えると、isNaN関数の結果は完全に論理的です!

本当の問題は、標準の文字列から数値への変換がなぜ機能するのかということです。文字列から数値への変換は、実際には「123」や「17.5e4」などの数値文字列を同等の数値に変換することを目的としています。変換では、最初の空白がスキップされるため( "123"が有効です)、残りを数値として解析しようとします。数値として解析できない場合( "x"は不可)、結果はNaNになります。しかし、空の文字列または空白のみの文字列が0に変換されるという明確な特別なルールがあります。これが変換を説明しています。

リファレンス:http : //www.ecma-international.org/ecma-262/5.1/#sec-9.3.1


1

この問題を解決するために、この簡単な関数を作成しました。

function isNumber(val) {
     return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};

数値(0〜9)ではなく、「-」または「。」ではなく、未定義、null、または空ではない文字をチェックし、一致するものがなければtrueを返します。:)


遅ればせながらこれをありがとう。これは私の問題を非常にうまく解決しました。
ヘンリー

1

他の説明のように、isNaN関数は空の文字列を検証前に数値に強制変換し、空の文字列を0(有効な数値)に変更します。ただし、空の文字列またはスペースのみの文字列を解析しようとすると、parseInt関数が返さNaNれることがわかりました。そのため、次の組み合わせはうまく機能しているようです:

if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');

このチェックは、正の数、負の数、および小数点付きの数で機能するため、一般的な数値のケースはすべてカバーされていると思います。


1

NaN !== "数字ではありません"

NaN 数値タイプの値です

これはECMAScriptのisNaN()の定義です

1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.

任意の値を数値に変換してみてください。

Number(" ") // 0
Number("x") // NaN
Number(null) // 0

値がかどうかを判断する場合はNaN、最初に数値に変換してみてください。


0

この機能は私のテストで機能するようでした

function isNumber(s) {
    if (s === "" || s === null) {
        return false;
    } else {
        var number = parseInt(s);
        if (number == 'NaN') {
            return false;
        } else {
            return true;
        }
    }
}

2
あなたの全体の機能を書き込むことができます:return !(s === "" || s === null || parseInt(s) == 'NaN');
ErikE


0

JavaScriptが内蔵されますisNaNの関数である- 「ダイナミックタイプオペレータ」 -デフォルトでは、期待されるべきです。したがって、(DTCプロセス中に)単純なtrueを生成するすべての値| などのfalseは"", " ", " 000"、NaNにはできません。

指定された引数が最初に次のように変換されることを意味します

function isNaNDemo(arg){
   var x = new Number(arg).valueOf();
   return x != x;
}

説明:

関数本体の最初の行では、(最初​​に)引数を数値オブジェクトに正常に変換しようとしています。そして、(第2)は、ドット演算子を使用して、我々は-私たち自身の便宜のために-すぐに、剥ぎ取りプリミティブ作成されたオブジェクトのを。

2行目で、私たちは前のステップで得られた値、およびという事実を利用取っているのNaNは:例えば、いなくてもそれ自体に、宇宙に何にも等しくないNaN == NaN >> false自分自身で最終的にそれを比較すること(不平等のために) 。

このようにして、関数returnは、指定されたargument-returnが数値オブジェクトへの変換に失敗した場合、つまり非数値の場合にのみtrueを返します。たとえば、NaN。


isNaNstatic()

ただし、静的型演算子の場合-必要に応じて、必要に応じて、次のようなはるかに単純な関数を記述できます。

function isNaNstatic(x){   
   return x != x;
}

また、引数が明示的にNaN数でない場合にfalseを返すように、DTCを完全に回避してください。したがって、以下に対するテスト:

isNaNStatic(" x"); // will return false それはまだ文字列だからです。

ただしisNaNStatic(1/"x"); // will of course return true.、たとえば次の ようになりますisNaNStatic(NaN); >> true

しかしisNaN、とは対照的に、isNaNStatic("NaN"); >> falseそれ(引数)は通常の文字列であるためです。

ps:isNaNの静的バージョンは、最新のコーディングシナリオで非常に役立ちます。そして、これが私がこれを投稿するために時間を費やした主な理由の1つである可能性が非常に高いでしょう。

よろしく。


0

isNAN(<argument>)与えられた引数が不正な数であるかどうかを知るための関数です。 isNaN引数を数値型に型キャストします。引数が数値かどうかを確認したい場合は?$.isNumeric()jQueryの関数を使用してください。

つまり、isNaN(foo)はisNaN(Number(foo))と同等です。明らかな理由により、すべての数値を文字列として数値として受け入れます。例のために。

isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true

0

私はこれを使います

    function isNotANumeric(val) {
    	if(val.trim && val.trim() == "") {
         return true;
      } else {
      	 return isNaN(parseFloat(val * 1));
      }
    }
    
    alert(isNotANumeric("100"));  // false
    alert(isNotANumeric("1a"));   // true
    alert(isNotANumeric(""));     // true
    alert(isNotANumeric("   "));  // true


0

空白であれば、特定の文字列の値をチェックしたりすると" "されるisNaNかもしれない例は、文字列の検証を実行してみてください:

// value = "123 " if (value.match(/\s/) || isNaN(value)) { // do something }

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