Warum funktioniert isNaN ( „“) gleich falsch
-
05-07-2019 - |
Frage
Ich habe eine kurze Frage (hoffe ich!). In JS, warum tut isNaN(" ")
auf falsch zu bewerten, aber isNaN(" x")
bewerten, um wahr?
Ich fahre numerische Operationen auf einem Texteingabefeld, und bin zu überprüfen, ob das Feld Null ist, „“, oder NaN. Wenn jemand Typen eine Handvoll Räume in das Feld, nicht meine Validierung auf allen drei, und ich bin verwirrt, warum es wird über die isNAN überprüfen.
Danke!
Lösung
JavaScript interpretiert eine leere Zeichenfolge als 0, der dann den isNAN Test fehlschlägt. Sie können zunächst auf die Saite verwenden ParseInt welche die leere Zeichenfolge zu 0. Das Ergebnis ist nicht konvertieren sollte dann isNAN versagen.
Andere Tipps
Sie können diese überraschend finden oder vielleicht auch nicht, aber hier ist einiger Test-Code Ihnen die wackyness der JavaScript-Engine zu zeigen.
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
so bedeutet dies, dass
" " == 0 == false
und
"" == 0 == false
und
"" != " "
Viel Spaß:)
Um es besser zu verstehen, öffnen Sie bitte Ecma-Script spec pdf auf Seite 43 "ToNumber Applied zum String-Typ"
, wenn eine Zeichenfolge, die eine numerische Syntax hat, die eine beliebige Anzahl von Leerraumzeichen enthalten kann, kann es zu Zahlentyp konvertiert werden. Leere Zeichenfolge auswertet auf 0 Auch der String ‚Unendlich‘ geben soll
isNaN('Infinity'); // false
Versuchen Sie es mit:
alert(isNaN(parseInt(" ")));
oder
alert(isNaN(parseFloat(" ")));
MDN
Grund für das Problem, das Sie stehen vor
Wenn das Argument der isNaN Funktion nicht vom Typ Zahl ist, wird der Wert zunächst in eine Zahl dazu gezwungen. Der resultierende Wert wird dann geprüft, um zu bestimmen, ob es NaN ist.
Sie können die folgende umfassende Antwort zu überprüfen, die auch den NaN Vergleich auf Gleichheit abdeckt.
Ich denke, es ist wegen der Javascript typing: ' '
auf Null umgewandelt wird, während 'x'
nicht:
alert(' ' * 1); // 0
alert('x' * 1); // NaN
Wenn Sie möchten, um eine genaue ISNUMBER Funktion implementieren, hier ist eine Möglichkeit, es von Javascript zu tun: The Good Parts von Douglas Crockford [Seite 105]
var isNumber = function isNumber(value) {
return typeof value === 'number' &&
isFinite(value);
}
Die Nicht-Ganz-Antwort zu korrigieren
Antonio Haleys sehr upvoted und Antwort akzeptiert hier macht eine falsche Annahme, dass dieser Prozess durch parseInt
Funktion des JavaScript geht:
Sie parseInt auf der Saite verwenden können ... Das Ergebnis sollte dann isNAN versagen.
Wir können leicht diese Aussage mit der Zeichenfolge "123abc"
entkräften:
parseInt("123abc") // 123 (a number...
isNaN("123abc") // true ...which is not a number)
Mit diesem können wir sehen, dass JavaScript die parseInt
Funktion "123abc"
als die Nummer 123
zurück, doch seine isNaN
Funktion sagt uns, dass "123abc"
nicht eine Zahl.
Die richtige Antwort
ECMAScript-262 definiert, wie die isNaN
Prüfung arbeitet in Abschnitt 18.2.3 .
18.2.3
isNaN
(Zahl)Die
isNaN
Funktion ist das%isNaN%
intrinsische Objekt. Wenn dieisNaN
Funktion mit einem Argument Nummer aufgerufen wird, werden die folgenden Schritte unternommen:
- Lassen Sie
num
sein?ToNumber(number)
.- Wenn
num
NaN
ist, kehrentrue
.- Ansonsten Rückgabe
false
.
Die ToNumber
Funktion verweist es wird auch in ECMAScript-262 der Abschnitt 7.1.3 . Hier bekommen wir gesagt, wie JavaScript Griffe Strings, die in dieser Funktion übergeben werden.
Das erste in der Frage gegebene Beispiel ist eine Zeichenkette nur Leerzeichen enthält. In diesem Abschnitt heißt es:
Ein
StringNumericLiteral
, die leer oder enthält nur Leerraum umgewandelt+0
.
Das " "
Beispiel String wird daher umgewandelt +0
, was eine Zahl ist.
Der gleiche Abschnitt auch lautet:
Wenn die Grammatik der
String
als Erweiterung vonStringNumericLiteral
nicht interpretieren kann, dann ist das Ergebnis vonToNumber
istNaN
.
Ohne in diesem Abschnitt enthalten alle Prüfungen unter Angabe der " x"
Beispiel in der Frage gegeben fällt in der obigen Bedingung, da es nicht als StringNumericLiteral
interpretiert werden kann. " x"
wird deshalb umgewandelt NaN
.
Ich bin nicht sicher, Warum , sondern um das Problem zu bekommen Sie immer Leerzeichen trimmen könnten vor dem Einchecken. Sie wollen wahrscheinlich, dass auf jeden Fall tun.
Die Funktion isNaN("")
führt eine String Nummer Zwang geben
ECMAScript 3-5 definiert die folgenden Rückgabewerte für die typeof-Operator:
- undefined
- Objekt (null, Objekte, Arrays)
- boolean
- number
- string
- Funktion
Besser unseren Test in einem Funktionskörper wickeln:
function isNumber (s) {
return typeof s == 'number'? true
: typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
: (typeof s).match(/object|function/)? false
: !isNaN(s)
}
Diese Funktion intented nicht Variable type zu testen, statt es testet den dazu gezwungen Wert . So werden zum Beispiel booleans und Strings in Zahlen dazu gezwungen, so vielleicht können Sie diese Funktion als isNumberCoerced()
anrufen möchten
, wenn es keine Notwendigkeit, zu testen für Typen andere als string und Zahl , dann wird der folgende Ausschnitt könnte als Teil einer Bedingung verwendet werden :
if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
alert("s is a number")
Ich schlage vor, Sie die folgende Funktion zu verwenden, wenn Sie wirklich eine richtige Kontrolle wollen, wenn es eine ganze Zahl ist:
function isInteger(s)
{
return Math.ceil(s) == Math.floor(s);
}
Die isNaN(" ")
falsch ist Teil des verwirrenden Verhaltens der isNaN
globalen Funktion aufgrund seines Zwang von Nicht-Zahlen in einen numerischen Typ ist.
MDN :
Seit den frühesten Versionen der
isNaN
Funktionsspezifikation, sein Verhalten für nicht-numerische Argumente hat verwirrend. Wenn das Argument derisNaN
Funktion nicht vom Typ Zahl ist, wird der Wert zunächst in eine Zahl dazu gezwungen. Der resultierende Wert wird dann geprüft, um zu bestimmen, ob esNaN
ist. So für nicht Zahlen, die, wenn sie in einem gültigen nicht-NaN numerischen Wert (insbesondere die leere Zeichenfolge und boolean Primitiven, die, wenn sie erzwungener numerische Werte Null oder Eins geben) auf numerische Art Ergebnis dazu gezwungen, die „falsch“ zurückgegebene Wert unerwartet sein kann; die leere Zeichenkette, zum Beispiel, ist sicherlich „keine Zahl.“
Beachten Sie auch, dass mit ECMAScript 6, gibt es auch jetzt ist die Number.isNaN
Methode, die nach MDN:
Im Vergleich zur globalen
isNaN()
Funktion,Number.isNaN()
leidet nicht das Problem mit Gewalt der Parameter auf eine Zahl zu konvertieren. Das bedeutet, es nun sicher ist, Wert zu übergeben, die normalerweise umwandeln würdenNaN
, ist aber nicht wirklich der gleiche Wert wieNaN
. Dies bedeutet auch, dass nur Werte der Typnummer, die auchNaN
sind, kehrentrue
.
Leider :
Auch die ECMAScript 6 Number.isNaN
Methode hat ihre eigenen Probleme, wie im Blog-Post skizziert - Befestigung des hässlichen JavaScript und ES6 NaN Problem .
Als andere erläuterten die Funktion isNaN
die leere Zeichenfolge in eine Zahl zwingen, bevor es Validieren, wodurch eine leere Zeichenfolge in 0 zu ändern (was eine gültige Zahl ist).
Ich fand jedoch, dass die parseInt
Funktion NaN
zurückkehren wird beim Versuch, eine leere Zeichenfolge oder eine Zeichenfolge mit nur Leerzeichen zu analysieren. Als solche ist die folgende Kombination gut zu funktionieren scheint:
if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');
Diese Prüfung wird für positive Zahlen arbeitet, negative Zahlen und Zahlen mit einem Komma, so dass ich glaube, dass es alle gängigen numerischen Fälle abdeckt.
Diese Funktion schien in meinen Tests arbeiten
function isNumber(s) {
if (s === "" || s === null) {
return false;
} else {
var number = parseInt(s);
if (number == 'NaN') {
return false;
} else {
return true;
}
}
}
Was ist
function isNumberRegex(value) {
var pattern = /^[-+]?\d*\.?\d*$/i;
var match = value.match(pattern);
return value.length > 0 && match != null;
}
Die isNaN
Funktion erwartet eine Zahl als Argument, so Argumente eines anderen Typs (in Ihrem Fall ein String) wird eine Zahl umgewandelt werden vor die tatsächliche Funktionslogik durchgeführt wird. (Beachten Sie, dass NaN
ist auch ein Wert vom Typ Zahl!)
Btw. das ist nicht unüblich für alle integrierte Funktionen - wenn sie ein Argument eines bestimmten Typs erwarten, wird das tatsächliche Argument unter Verwendung der Standard-Konvertierungsfunktionen umgewandelt werden. Es gibt Standard-Konvertierungen zwischen allen Grundtypen (Bool, String, Anzahl, Objekt, Datum, null, nicht definiert.)
Die Standardkonvertierung für String
zu Number
mit Number()
explizit aufgerufen werden. So können wir sehen, dass:
-
Number(" ")
ausgewertet0
-
Number(" x")
ausgewertetNaN
Dieses Anbetracht das Ergebnis der isNaN
Funktion ist völlig logisch!
Die eigentliche Frage ist, warum die Standard-String-to-Nummer Konvertierung funktioniert wie es funktioniert. Die String-to-Nummer Umwandlung ist wirklich gedacht numerische Zeichenfolge zu konvertieren wie „123“ oder „17.5e4“ auf die entsprechenden Zahlen. Die Umwandlung erste anfängliche Leerüberspringt (so „123“ gelten), und versucht dann, die Reste als Zahl zu parsen. Wenn es nicht parseable als Zahl ist ( „x“ ist nicht), dann ist das Ergebnis NaN. Aber es ist die explizite Sonderregel, die eine Zeichenkette, die leer oder nur Leerzeichen sind umgewandelt zu 0, so dass dies die Umwandlung erklärt.
Referenz: http: //www.ecma-international .org / ECMA-262 / 5,1 / # sec-9.3.1
Ich schrieb diese schnelle kleine Funktion zu helfen, dieses Problem zu lösen.
function isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
Es prüft nur für alle Zeichen, die nicht numerisch (0-9) sind, die nicht sind ‚-‘ ‚‘ oder, und das ist nicht definiert, null oder leer und true zurück, wenn es keine Übereinstimmungen gibt. :)
Die JavaScript Built-in isNaN Funktion, ist - wie sollte standardmäßig zu erwarten - ein "Dynamic Typ Operator".
Daher werden alle Werte, die (während des DTC-Prozess) ein einfaches wahr ergeben können | falsch wie "", " ", " 000"
kann NaN nicht sein.
Was bedeutet, dass die Argument geliefert wird zuerst durchläuft eine Umwandlung wie in:
function isNaNDemo(arg){
var x = new Number(arg).valueOf();
return x != x;
}
Erklärung:
In der oberen Zeile der Funktion Körper, wir sind (erste) versuchen, erfolgreich das Argument in eine Anzahl Objekt zu konvertieren. Und (zweite), mit dem Punktoperator wir sind - für unsere eigene Bequemlichkeit -. Sofort abzieht, primitiver Wert des erzeugten Objekts
In der zweiten Zeile, wir nehmen den Wert in dem vorhergehenden Schritt erhalten, und den Vorteil der Tatsache, dass NaN ist nicht gleich alles im Universum, nicht einmal zu sich selbst, zum Beispiel: NaN == NaN >> false
, um es schließlich zu vergleichen (für Ungleichheit) mit sich selbst
Auf diese Weise der Funktion Ertrag abwerfen wird true nur, wenn und nur dann, wenn die bereitgestellte Argument-Rückkehr, ist ein gescheiterter Versuch der Umwandlung in eine Anzahl Objekt, das heißt , eine not-a-number-Nummer; z.B. NaN.
isNaNstatic ()
Doch für einen statischen Typen Betreiber - bei Bedarf und bei Bedarf - können wir eine viel einfachere Funktion wie schreiben:
function isNaNstatic(x){
return x != x;
}
Und das DTC ganz zu vermeiden, so dass, wenn das Argument nicht explizit eine NaN Zahl ist, wird es false zurück. Darum Tests gegen die folgenden:
isNaNStatic(" x"); // will return false
weil es ist immer noch ein String.
Allerdings:
isNaNStatic(1/"x"); // will of course return true.
als Wille zum Beispiel isNaNStatic(NaN); >> true
.
Aber im Gegensatz zu isNaN
, die isNaNStatic("NaN"); >> false
, weil es (das Argument) ist ein gewöhnlicher String.
P. S .: Die statische Version von isNaN kann in moderner Codierung Szenarien sehr nützlich sein. Und es kann sehr wohl einer der Hauptgründe sein, ich meine Zeit für dieses Posting nahm.
Viele Grüße.
isNAN(<argument>)
ist eine Funktion, zu sagen, ob gegebenes Argument ist illegal Zahl.
isNaN
Typumwandlungen, die Argumente in Zahlentyp. Wenn Sie möchten, zu überprüfen, ob Argument numerisch ist oder nicht? Bitte verwenden Sie $.isNumeric()
Funktion in jQuery.
Das heißt, isNaN (foo) entspricht isNaN (Anzahl (foo)) Er akzeptiert keine Strings alle Zahlen als Zahlen aus offensichtlichen Gründen haben. Für ex.
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
Ich benutze diese
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
! == "keine Zahl"
NaN
ist ein Wert, der Nummer Typ
Dies ist eine Definition von isNaN () in ECMAScript
1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.
Versuchen Sie einen beliebigen Wert Zahl zu konvertieren.
Number(" ") // 0
Number("x") // NaN
Number(null) // 0
Wenn Sie feststellen möchten, ob der Wert NaN
ist, sollten Sie versuchen, es zu einem Zahlenwert zu konvertieren zunächst.
Bei der Prüfung, ob bestimmte Zeichenfolge-Wert mit Leerzeichen oder " "
is isNaN
versuchen vielleicht String-Validierung, darunter:
// value = "123 "
if (value.match(/\s/) || isNaN(value)) {
// do something
}