isNaN(“ ”) が false に等しいのはなぜですか
-
05-07-2019 - |
質問
簡単な質問があります (そう願っています!)。JS では、なぜ 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
and
"" == 0 == false
しかし
"" != " "
楽しんでください:)
理解を深めるために、 Ecma-Script spec pdf を開いてください。 a> 43ページの"文字列型に適用されるToNumber"
文字列に数値構文があり、任意の数の空白文字を含めることができる場合、数値型に変換できます。空の文字列は0と評価されます。また、文字列「Infinity」は次のようになります
isNaN('Infinity'); // false
使用してみてください:
alert(isNaN(parseInt(" ")));
または
alert(isNaN(parseFloat(" ")));
isNaN関数の引数が数値型ではない場合、値は最初に数値に強制変換されます。次に、結果の値をテストして、NaNかどうかを判断します。
同等のNaN比較についても説明している次の包括的な回答を確認することをお勧めします。
であるかどうかをテストする方法
Javascriptのタイピングが原因だと思います: ''
はゼロに変換されますが、 'x'
はそうではありません:
alert(' ' * 1); // 0
alert('x' * 1); // NaN
正確なisNumber関数を実装する場合、Douglas Crockfordによる Javascript:The Good Parts [105ページ]からそれを行う1つの方法を次に示します
var isNumber = function isNumber(value) {
return typeof value === 'number' &&
isFinite(value);
}
完全に正解ではない回答
Antonio Haleyの非常に支持され受け入れられた回答は、このプロセスがJavaScriptの parseInt
関数:
文字列でparseIntを使用できます...結果はisNANに失敗します。
文字列" 123abc"
を使用すると、このステートメントを簡単に反証できます:
parseInt("123abc") // 123 (a number...
isNaN("123abc") // true ...which is not a number)
これにより、JavaScriptの parseInt
関数が数値 123
として" 123abc"
を返しますが、その isNaN
関数は、" 123abc"
は数字ではないことを示しています。
正解
ECMAScript-262は、isNaN チェックがどのように機能するかを定義します。 >セクション18.2.3 。
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
に変換されます。
なぜかはわかりませんが、問題を回避するには、チェックする前に常に空白を削除できます。とにかくそれをしたいでしょう。
関数 isNaN("")
は、 String to Number type coercion
- 未定義
- オブジェクト(null、オブジェクト、配列)
- ブール
- number
- string
- 関数
テストを関数本体にラップする方が良い:
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")
整数かどうかを適切にチェックする必要がある場合は、次の関数を使用することをお勧めします。
function isInteger(s)
{
return Math.ceil(s) == Math.floor(s);
}
isNaN("")
はfalseです。これは、非数値の数値型への強制により、 isNaN
グローバル関数の混乱する動作の一部です。 。
MDN :
isNaN
関数仕様の最も初期のバージョンなので、非数値引数の動作は混乱を招きました。isNaN
関数の引数が数値型ではない場合、値は最初に数値に強制変換されます。次に、結果の値をテストして、NaN
であるかどうかを判断します。したがって、数値型に強制されたときに有効な非NaN数値(特に、強制されたときに数値が0または1になる空の文字列およびブールプリミティブ)になる非数値の場合、「false」戻り値は予期しない場合があります。たとえば、空の文字列は必ず「数字ではない」
ECMAScript 6では、 Number.isNaN
メソッドもあることに注意してください。MDNによると、
グローバルな
isNaN()
関数と比較して、Number.isNaN()
は、パラメーターを強制的に数値に変換する問題を抱えていません。これは、通常はNaN
に変換されるが、実際にはNaN
と同じ値ではない値を渡すことが安全であることを意味します。これはまた、NaN
である型番号の値のみがtrue
を返すことを意味します。
残念ながら:
ECMAScript 6の Number.isNaN
メソッドにも、ブログ投稿で説明されているように、独自の問題があります-いJavaScriptとES6 NaNの問題の修正。
他で説明したように、 isNaN
関数は空の文字列を検証する前に強制的に数値に変換し、空の文字列を0(有効な数値)に変更します。
ただし、空の文字列またはスペースのみの文字列を解析しようとすると、 parseInt
関数が NaN
を返すことがわかりました。そのため、次の組み合わせはうまく機能しているようです:
if(isNaN(string)|| isNaN(parseInt(string)))console.log( 'Not a number!');
このチェックは、正の数値、負の数値、および小数点付きの数値に対して機能するため、すべての一般的な数値のケースをカバーすると考えています。
この関数は私のテストで機能しているように見えました
function isNumber(s) {
if (s === "" || s === null) {
return false;
} else {
var number = parseInt(s);
if (number == 'NaN') {
return false;
} else {
return true;
}
}
}
はどうですか
function isNumberRegex(value) {
var pattern = /^[-+]?\d*\.?\d*$/i;
var match = value.match(pattern);
return value.length > 0 && match != null;
}
isNaN
関数は引数として数値を想定しているため、他のタイプの引数(あなたの場合は文字列)は実際の関数ロジックの前に数値に変換されます は発表された。 ( 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 isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
数値(0-9)ではなく、「-」または「。」ではなく、未定義、ヌル、または空ではない文字をチェックし、一致しない場合はtrueを返します。 :)
の JavaScript 内蔵 はNaN この関数は、デフォルトで予想されるとおり、「動的型演算子」です。したがって、(DTCプロセス中に)単純なtrueを生成する可能性のあるすべての値|のような偽 "", " ", " 000"
, 、NaN にすることはできません。
つまり、 口論 供給されたものは最初に 変換 次のように:
function isNaNDemo(arg){
var x = new Number(arg).valueOf();
return x != x;
}
説明:
関数本体の一番上の行では、(最初に) 引数を数値オブジェクトに正常に変換しようとしています。そして (2 番目)、ドット演算子を使用して、私たち自身の便宜上、すぐに削除します。 の 原生的 価値 作成されたオブジェクトの。
2 行目では、前のステップで取得した値と、次の利点を利用しています。 NaN 宇宙の何とも等しくなく、それ自体とさえも等しくありません。例: NaN == NaN >> false
最後にそれを(不平等について)それ自体と比較します。
このようにして、関数の戻り値は次のようになります。 真実 指定された引数戻り値が数値オブジェクト、つまり非数値への変換に失敗した場合のみ。たとえば、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
それ(引数)は通常の文字列であるためです。
追記:isNaN の静的バージョンは、最新のコーディング シナリオで非常に役立ちます。そしてそれが、私がこれを投稿するのに時間を費やした主な理由の 1 つである可能性があります。
よろしく。
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
これを使用
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
NaN
!==" not a number"
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
であるかどうかを判断する場合は、最初に値を数値に変換する必要があります。
特定の文字列値が空白または"であるかどうかを確認する場合"
is isNaN
は、文字列検証の実行を試みる場合があります。例:
// value =" 123"
if(value.match(/ \ s /)|| isNaN(value)){
//何かをする
}