web-dev-qa-db-ja.com

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

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

テキスト入力フィールドで数値演算を実行しています。フィールドがnull""、またはNaN。誰かがフィールドにいくつかのスペースを入力すると、3つすべてで検証が失敗し、isNaNチェックを通過する理由がわかりません。

150
IVR Avenger

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

145
Antonio Haley

これは驚くかもしれませんが、多分そうでないかもしれませんが、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

しかし

"" != " "

楽しんで :)

78
Nick Berardi

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

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

isNaN('Infinity'); // false
16
Rafael

使用してみてください:

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

または

alert(isNaN(parseFloat("    ")));
15
bendewey

MDN 直面している問題の理由から

IsNaN関数の引数が数値型ではない場合、値は最初に数値に強制変換されます。次に、結果の値をテストして、NaNかどうかを判断します。

NaN比較の平等についても説明している次の包括的な回答を確認してください。

JavaScript変数がNaNであるかどうかをテストする方法

6
dopeddude

Javascriptのタイピングが原因だと思います:' 'はゼロに変換されますが、'x'はそうではありません:

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

完全ではない答え

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

文字列に対してparseIntを使用できます...結果はisNANに失敗します。

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

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

これにより、JavaScriptのparseInt関数は_"123abc"_を数値_123_として返しますが、そのisNaN関数は_"123abc"_is't数字。

正しい答え

ECMAScript-262は、 セクション18.2.3isNaNチェックがどのように機能するかを定義します。

18.2.3 isNaN(数値)

isNaN関数は_%isNaN%_組み込みオブジェクトです。 isNaN関数が1つの引数番号で呼び出されると、次の手順が実行されます。

  1. numを? ToNumber(number)
  2. numNaNの場合、trueを返します。
  3. それ以外の場合は、falseを返します。

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

質問の最初の例は、空白文字のみを含む文字列です。このセクションでは、次のことを説明しています。

空または空白のみを含むStringNumericLiteralは、_+0_に変換されます。

したがって、_" "_の例の文字列は、数値である_+0_に変換されます。

同じセクションでは次のことも述べています。

文法がStringStringNumericLiteralの拡張として解釈できない場合、ToNumberの結果はNaNになります。

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

4
James Donnelly

正確なisNumber関数を実装する場合は、Douglas CrockfordによるJavascript:The Good Partsから実行する1つの方法があります[105ページ]

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

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

2
Joel Coehoorn

関数isNaN("")は、String to Numbertype coercionを実行します

ECMAScript 3-5はtypeof演算子の以下の戻り値を定義します:

  • undefined
  • オブジェクト(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)
}
_

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

stringおよびnumber以外のtypesをテストする必要がない場合、次のスニペットが何らかの条件の一部として使用される場合があります。

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

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

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

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

1
Nadav

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

ところでこれはall組み込み関数に共通です-特定の型の引数が必要な場合、実際の引数は標準の変換関数を使用して変換されます。すべての基本型(bool、string、number、object、date、null、undefined)の間には標準的な変換があります。

Stringから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
JacquesB

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

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

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

From [〜#〜] mdn [〜#〜]

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

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

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

残念ながら

ECMAScript 6の_Number.isNaN_メソッドでさえ、ブログ投稿で概説されているように、独自の問題があります- いJavaScriptとES6 NaNの問題を修正する

1
lucono

JavaScript組み込みのisNaN関数は、-デフォルトで予想されるとおり- 「動的型演算子」。したがって、(DTCプロセス中に)単純なtrue | _"", " ", " 000"_などのfalseはNaNにはできません。

指定されたargumentが最初にconversionを受けることを意味します:

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

説明:

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

2行目では、前のステップで取得した値を使用していますが、NaNという事実の利点は宇宙のあらゆるものと同等ではなく、それ自体でさえもありません。例:_NaN == NaN >> false_は最終的にそれを(不平等のために)それ自身と比較します。

このようにして、関数の戻り値はtrueを生成します。指定されたargument-returnが失敗した場合にのみ数値オブジェクトへの変換、つまり非数値例: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は(引数)が通常の文字列であるためです。

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

よろしく。

0
Bekim Bacaj

どう?

function isNumberRegex(value) {        
    var pattern = /^[-+]?\d*\.?\d*$/i;
    var match = value.match(pattern);
    return value.length > 0 && match != null;
}
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
kiranvj

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

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

数値(0-9)ではなく、「-」や「。」ではなく、未定義、ヌル、空ではない文字をチェックし、一致しない場合はtrueを返します。 :)

0
XtraSimplicity

この機能は私のテストで機能しているように見えました

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

特定の文字列値が空白または_" "_ is isNaNであるかどうかを確認するときは、文字列の検証を実行してみてください。例:

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

0
Channox

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であるかどうかを判断する場合は、最初に値をNumber値に変換する必要があります。

0
bitfishxyz

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

つまり、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
Om Prakash Sao