JavaScriptでは、なぜisNaN(" ")
はfalse
に評価されますが、isNaN(" x")
はtrue
に評価されますか?
テキスト入力フィールドで数値演算を実行しています。フィールドがnull
、""
、またはNaN
。誰かがフィールドにいくつかのスペースを入力すると、3つすべてで検証が失敗し、isNaN
チェックを通過する理由がわかりません。
JavaScriptは空の文字列を0として解釈し、isNANテストに失敗します。空の文字列を0に変換しない文字列に対して最初にparseIntを使用できます。結果はisNANに失敗します。
これは驚くかもしれませんが、多分そうでないかもしれませんが、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
しかし
"" != " "
楽しんで :)
理解を深めるには、43ページの Ecma-Script spec pdf を開いてください。「文字列型に適用されるToNumber」
文字列に数値構文があり、任意の数の空白文字を含めることができる場合、数値型に変換できます。空の文字列は0と評価されます。また、文字列 'Infinity'は
isNaN('Infinity'); // false
使用してみてください:
alert(isNaN(parseInt(" ")));
または
alert(isNaN(parseFloat(" ")));
MDN
直面している問題の理由から
IsNaN関数の引数が数値型ではない場合、値は最初に数値に強制変換されます。次に、結果の値をテストして、NaNかどうかを判断します。
NaN比較の平等についても説明している次の包括的な回答を確認してください。
Javascriptのタイピングが原因だと思います:' '
はゼロに変換されますが、'x'
はそうではありません:
alert(' ' * 1); // 0
alert('x' * 1); // NaN
アントニオヘイリー の非常に支持され受け入れられた答え は、このプロセスが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.3 でisNaN
チェックがどのように機能するかを定義します。
18.2.3
isNaN
(数値)
isNaN
関数は_%isNaN%
_組み込みオブジェクトです。isNaN
関数が1つの引数番号で呼び出されると、次の手順が実行されます。
num
を?ToNumber(number)
。num
がNaN
の場合、true
を返します。- それ以外の場合は、
false
を返します。
参照するToNumber
関数は、 ECMAScript-262のセクション7.1.3 でも定義されています。ここでは、この関数に渡される文字列をJavaScriptがどのように処理するかを説明します。
質問の最初の例は、空白文字のみを含む文字列です。このセクションでは、次のことを説明しています。
空または空白のみを含む
StringNumericLiteral
は、_+0
_に変換されます。
したがって、_" "
_の例の文字列は、数値である_+0
_に変換されます。
同じセクションでは次のことも述べています。
文法が
String
をStringNumericLiteral
の拡張として解釈できない場合、ToNumber
の結果はNaN
になります。
そのセクション内に含まれるすべてのチェックを引用しないと、質問で示されている_" x"
_の例は、StringNumericLiteral
として解釈できないため、上記の条件に該当します。したがって、_" x"
_はNaN
に変換されます。
正確なisNumber関数を実装する場合は、Douglas CrockfordによるJavascript:The Good Partsから実行する1つの方法があります[105ページ]
var isNumber = function isNumber(value) {
return typeof value === 'number' &&
isFinite(value);
}
whyはわかりませんが、問題を回避するには、チェックする前に常に空白を削除できます。とにかくそれをしたいと思うでしょう。
関数isNaN("")
は、String to Numbertype coercionを実行します
ECMAScript 3-5はtypeof演算子の以下の戻り値を定義します:
テストを関数本体でラップする方が良い:
_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")
_
他で説明したように、isNaN
関数は空の文字列を検証する前に強制的に数値に変換し、空の文字列を0(有効な数値)に変更します。ただし、空の文字列またはスペースのみの文字列を解析しようとすると、parseInt
関数がNaN
を返すことがわかりました。そのため、次の組み合わせはうまく機能しているようです:
if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');
このチェックは、正の数値、負の数値、および小数点付きの数値に対して機能するため、一般的な数値のすべてのケースをカバーすると考えています。
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
整数かどうかを適切にチェックする必要がある場合は、次の関数を使用することをお勧めします。
function isInteger(s)
{
return Math.ceil(s) == Math.floor(s);
}
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の問題を修正する 。
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つである可能性が非常に高いかもしれません。
よろしく。
どう?
function isNumberRegex(value) {
var pattern = /^[-+]?\d*\.?\d*$/i;
var match = value.match(pattern);
return value.length > 0 && match != null;
}
これを使う
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
この問題を解決するために、この簡単な機能を作成しました。
function isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
数値(0-9)ではなく、「-」や「。」ではなく、未定義、ヌル、空ではない文字をチェックし、一致しない場合はtrueを返します。 :)
この機能は私のテストで機能しているように見えました
function isNumber(s) {
if (s === "" || s === null) {
return false;
} else {
var number = parseInt(s);
if (number == 'NaN') {
return false;
} else {
return true;
}
}
}
特定の文字列値が空白または_" "
_ is isNaN
であるかどうかを確認するときは、文字列の検証を実行してみてください。例:
// value = "123 " if (value.match(/\s/) || isNaN(value)) { // do something }
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値に変換する必要があります。
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