179

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

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

4

25 に答える 25

85

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

しかし

"" != " "

楽しむ :)

于 2009-05-05T15:34:54.527 に答える
18

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

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

isNaN('Infinity'); // false
于 2009-05-05T15:32:00.837 に答える
7

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

isNaN 関数への引数が Number 型でない場合、値はまず Number に強制変換されます。結果の値は、NaN かどうかを判断するためにテストされます。

等号の NaN 比較もカバーする次の包括的な回答を確認することをお勧めします。

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

于 2015-05-03T07:25:39.173 に答える
6

完全に正しいとは言えない答え

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

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

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

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

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

正解

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

18.2.3 isNaN(数値)

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

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

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

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

空であるStringNumericLiteralか空白のみを含む は に変換され+0ます。

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

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

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

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

于 2016-03-10T12:11:38.117 に答える
4

正確なisNumber関数を実装したい場合は、Javascriptから実装する1つの方法があります。DouglasCrockfordによるGoodParts [105ページ]

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}
于 2009-05-05T15:38:23.287 に答える
3

この関数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")
于 2013-09-13T21:38:09.747 に答える
2

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

function isInteger(s)
{
   return Math.ceil(s) == Math.floor(s);
}
于 2010-10-26T09:39:40.603 に答える
2

これは、非数値を数値型に強制するためisNaN(" ")、グローバル関数の紛らわしい動作の一部です。isNaN

MDNから:

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

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

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

残念ながら

ECMAScript 6Number.isNaNメソッドにも独自の問題があります。ブログ記事の修正、醜い JavaScript と ES6 NaN の問題で概説されています。

于 2015-04-29T15:22:11.520 に答える
1

この問題を解決するために、この簡単な小さな関数を書きました。

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

数値 (0 ~ 9) でなく、'-' または '.' でなく、未定義、null、または空ではない文字を単純にチェックし、一致するものがない場合は true を返します。:)

于 2015-12-14T00:18:08.487 に答える
1

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

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

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

于 2017-08-28T03:15:11.183 に答える
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 は、指定された引数 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.

しかし、 とは反対にisNaNisNaNStatic("NaN"); >> falseそれ (引数) は通常の文字列だからです。

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

よろしく。

于 2017-01-08T01:01:53.293 に答える
0

Number クラスに固有のメソッドを用意し (parseInt のような変換を行う他の関数では、これらの値の一部に対して異なる出力が得られるため)、プロトタイプの継承を使用すると便利です。

Object.assign(Number.prototype, {
  isNumericallyValid(num) {
    if (
      num === null
      || typeof num === 'boolean'
      || num === ''
      || Number.isNaN(Number(num))
    ) {
      return false;
    }
    return true;
  }
});
于 2020-09-01T02:20:46.747 に答える