JavaScript-Nullprüfung

170

Ich bin auf folgenden Code gestoßen:

function test(data) {
    if (data != null && data !== undefined) {
        // some code here
    }
}

Ich bin etwas neu in JavaScript, aber aufgrund anderer Fragen, die ich hier gelesen habe, habe ich den Eindruck, dass dieser Code nicht viel Sinn macht.


Diese Antwort besagt insbesondere, dass

Sie erhalten eine Fehlermeldung, wenn Sie in einem anderen Kontext als auf eine undefinierte Variable zugreifen typeof.

Update: Die (Zitat der) Antwort oben kann irreführend sein. Es sollte "eine nicht deklarierte Variable" anstelle von "eine nicht definierte Variable" stehen .

Wie ich herausgefunden habe, werden in den Antworten von Ryan ♦ , Maerics und Nwellnhof die Variablen für die Argumente immer deklariert, selbst wenn für eine Funktion keine Argumente angegeben werden. Diese Tatsache beweist auch den ersten Punkt in der Liste unten als falsch.


Nach meinem Verständnis können die folgenden Szenarien auftreten:

  • Die Funktion wurde ohne Argumente aufgerufen, wodurch dataeine undefinierte Variable erstellt und ein Fehler ausgelöst wurde data != null.

  • Die Funktion wurde speziell mit null(oder undefined) als Argument aufgerufen. In diesem Fall data != nullschützt sie bereits den inneren Code und macht ihn && data !== undefinedunbrauchbar.

  • Die Funktion wurde mit einem Nicht-Null-Argument aufgerufen. In diesem Fall werden sowohl data != null und als auch trivial übergeben data !== undefined.

F: Ist mein Verständnis richtig?


Ich habe Folgendes in der Firefox-Konsole versucht:

--
[15:31:31.057] false != null
[15:31:31.061] true
--
[15:31:37.985] false !== undefined
[15:31:37.989] true
--
[15:32:59.934] null != null
[15:32:59.937] false
--
[15:33:05.221] undefined != null
[15:33:05.225] false
--
[15:35:12.231] "" != null
[15:35:12.235] true
--
[15:35:19.214] "" !== undefined
[15:35:19.218] true

Ich kann keinen Fall herausfinden , wo die data !== undefined nach data != null irgendwelcher sein könnte.

afsantos
quelle
9
Einfach benutzen if (data). Es ist eine mnemonische Javascript-Methode, um zu überprüfen, ob die dataVariable true ergibt. undefined, null, False, 0, leere Zeichenfolge, leere Array und (?) Objekt ohne Eigenschaften das Ergebnis falsch, der Rest ist wahr.
J0HN
20
@ J0HN - Verwenden if(data)würde bedeuten, dass er nicht übergeben kann falseoder 0als Werte für data.
Techfoobar
@ J0HN Die gleiche Antwort, die ich erwähne, besagt auch, dass: if(typeof someUndefVar == whatever) -- worksund if(someUnderVar) -- error.
Afsantos
2
Es soll wahrscheinlich sein data !== null && data !== undefined, was äquivalent zu data != nullwas äquivalent zu ist data != undefined. Die erstere Form wird tendenziell bevorzugt, da sie die Bedingungen expliziter beschreibt, während es leicht zu übersehen ist, dass beide nullund undefinedmit den beiden späteren Bedingungen überprüft werden.
zzzzBov
2
Übrigens sind explizite Tests für undefinedIMO ein Codegeruch. Es ist kein geschütztes Schlüsselwort wie null, es ist eine Variable, die zufällig undefiniert ist. Dies ist völlig gültig und wird Ihren Code brechen:undefined = 1
Izkata

Antworten:

106

Eine „undefinierte Variable“ unterscheidet sich vom Wert undefined.

Eine undefinierte Variable:

var a;
alert(b); // ReferenceError: b is not defined

Eine Variable mit dem Wert undefined:

var a;
alert(a); // Alerts “undefined”

Wenn eine Funktion ein Argument annimmt, wird dieses Argument immer deklariert, auch wenn sein Wert lautet undefined, sodass kein Fehler auftritt. Sie sind recht != nulldurch , gefolgt !== undefinednutzlos, though.

Ry-
quelle
32
data !== null && data !== undefinedwürde aber Sinn machen.
Bfavaretto
@bfavaretto: Ja, es könnte also tatsächlich ein Tippfehler sein. Aber Sie wissen nie ...: D
Ry-
1
Genau wie ich dachte, danke für die Klarstellung. Ich denke auch nicht, dass es ein Tippfehler ist. Ich habe im gesamten Skript ein Find-and-Count durchgeführt und es wurden 10 Vorkommen gefunden, also ... Ich denke, der Autor muss auch diesbezüglich geklärt werden.
Afsantos
2
Scratch mein Kommentar oben: würde eigentlich data != nullfür beide nullund prüfen undefined(aber interessanterweise nur für nullund undefinedund nicht für die anderen falschen Werte).
Bfavaretto
90

In JavaScript nullhandelt es sich um ein spezielles Singleton-Objekt, das hilfreich ist, um "kein Wert" zu signalisieren. Sie können dies durch Vergleich testen. Wie in JavaScript üblich, empfiehlt es sich, den ===Operator zu verwenden, um verwirrende Typenzwänge zu vermeiden:

var a = null;
alert(a === null); // true

Wie @rynah erwähnt, ist "undefiniert" in JavaScript etwas verwirrend. Es ist jedoch immer sicher zu testen, ob die typeof(x)Zeichenfolge "undefiniert" ist, auch wenn "x" keine deklarierte Variable ist:

alert(typeof(x) === 'undefined'); // true

Variablen können auch den "undefinierten Wert" haben, wenn sie nicht initialisiert werden:

var y;
alert(typeof(y) === 'undefined'); // true

Alles in allem sollte Ihr Scheck folgendermaßen aussehen:

if ((typeof(data) !== 'undefined') && (data !== null)) {
  // ...

Da die Variable "Daten" jedoch immer definiert ist, da es sich um einen formalen Funktionsparameter handelt, ist die Verwendung des Operators "typeof" nicht erforderlich und Sie können sicher direkt mit dem "undefinierten Wert" vergleichen.

function(data) {
  if ((data !== undefined) && (data !== null)) {
    // ...

Dieses Snippet bedeutet: "Wenn die Funktion mit einem Argument aufgerufen wurde, das definiert ist und nicht null ist ..."

Maerics
quelle
5
Warum sollte es aber so aussehen? != nullwird für alle Werte außer nullund gelten undefined, und wir sind sicher, dass diese Variable deklariert ist. typeofin anderen Situationen kann es sogar gefährlich sein - was ist, wenn Sie den Variablennamen falsch eingeben? Das kann lange Zeit unentdeckt bleiben, da kein Fehler vorliegt.
Ry-
@maerics Wenn ich also Ihrer Antwort bei einer Nullprüfung wie dem obigen Szenario richtig folgen würde, würden Sie überhaupt keinen !=strengen Vergleich verwenden !==?
Afsantos
@rynah: Ich nehme nicht an, genug über die Gesamtlösung von OP zu wissen, um zu wissen, ob ein Nulltest angemessen ist oder nicht, aber ich habe ihn bearbeitet, um die Tatsache zu erwähnen, dass die Verwendung von "typeof" nicht erforderlich ist.
Maerics
@afsantos: In Wirklichkeit glaube ich nicht, dass viele (irgendwelche?) Werte in null konvertiert werden; Es wird jedoch empfohlen, einen strengen Vergleich ( ===) zu verwenden, es sei denn, Sie wissen wirklich, was Sie tun, und möchten einen Vergleich nach der Konvertierung ( ==).
Maerics
1
@Izkata: Löscht jede Bibliothek, die versucht, sie neu zu definieren undefined. Auch Safari auf dem iPad wird dies unter keinen Umständen tun. Du kannst nicht einmal delete window.undefined.
Ry-
10

In Ihrem Fall verwenden data==null(was NUR für null und undefiniert gilt - konzentrieren Sie sich beim zweiten Bild auf Zeilen / Spalten, die nicht definiert sind)

Hier haben Sie alle ( src ):

wenn

Geben Sie hier die Bildbeschreibung ein

== (seine Negation ! = )

Geben Sie hier die Bildbeschreibung ein

=== (seine Verneinung ! == )

Geben Sie hier die Bildbeschreibung ein

Kamil Kiełczewski
quelle
8

F: Die Funktion wurde ohne Argumente aufgerufen, wodurch Daten zu einer undefinierten Variablen wurden und ein Fehler bei data! = Null ausgelöst wurde.

A: Ja, datawird auf undefiniert gesetzt. Siehe Abschnitt 10.5 Deklarationsbindung Instanziierung der Spezifikation. Der Zugriff auf einen undefinierten Wert führt jedoch nicht zu einem Fehler. Sie verwechseln dies wahrscheinlich mit dem Zugriff auf eine nicht deklarierte Variable im strengen Modus, was einen Fehler auslöst.

F: Die Funktion wurde speziell mit null (oder undefiniert) als Argument aufgerufen. In diesem Fall schützt data! = Null bereits den inneren Code und macht && data! == undefined unbrauchbar.

F: Die Funktion wurde mit einem Nicht-Null-Argument aufgerufen. In diesem Fall werden sowohl Daten! = Null als auch Daten! == undefiniert trivial übergeben.

A: Richtig. Beachten Sie, dass die folgenden Tests gleichwertig sind:

data != null
data != undefined
data !== null && data !== undefined

Siehe Abschnitt 11.9.3 Der abstrakte Gleichheitsvergleichsalgorithmus und Abschnitt 11.9.6 Der strikte Gleichheitsvergleichsalgorithmus der Spezifikation.

nwellnhof
quelle
Ich habe nicht mit nicht deklarierten Variablen verwechselt, ich wusste wirklich nicht, wie es funktioniert, wenn keine Argumente angegeben wurden. Ich war überzeugt, dass es das dataüberhaupt nicht geben würde, anstatt darauf eingestellt zu sein undefined. Ich schätze die Klarstellung, und diese Referenzen haben mir geholfen, genauer zu verstehen, wie beide Gleichheiten funktionieren.
Afsantos
3

Ich denke, das Testen von Variablen auf Werte, die Sie nicht erwarten, ist im Allgemeinen keine gute Idee. Weil Sie den Test als Ihren betrachten können, als würden Sie eine schwarze Liste verbotener Werte schreiben. Aber was ist, wenn Sie vergessen, alle verbotenen Werte aufzulisten? Jemand, sogar Sie, kann Ihren Code knacken, indem er einen unerwarteten Wert übergibt. Ein geeigneterer Ansatz ist also so etwas wie eine Whitelist - Variablen werden nur auf die erwarteten Werte getestet, nicht unerwartet. Wenn Sie beispielsweise erwarten, dass der Datenwert stattdessen eine Zeichenfolge ist:

function (data) {
  if (data != null && data !== undefined) {
    // some code here
    // but what if data === false?
    // or data === '' - empty string?
  }
}

mach so etwas:

function (data) {
  if (typeof data === 'string' && data.length) {
    // consume string here, it is here for sure
    // cleaner, it is obvious what type you expect
    // safer, less error prone due to implicit coercion
  } 
}

quelle
2

typeof foo === "undefined"ist anders als foo === undefined, verwirren Sie sie nie. typeof foo === "undefined"ist was du wirklich brauchst. Verwenden Sie auch !==anstelle von!=

So kann die Aussage geschrieben werden als

function (data) {
  if (typeof data !== "undefined" && data !== null) {
    // some code here
  }
}

Bearbeiten:

Sie können nicht foo === undefinedfür nicht deklarierte Variablen verwenden.

var t1;

if(typeof t1 === "undefined")
{
  alert("cp1");
}

if(t1 === undefined)
{
  alert("cp2");
}

if(typeof t2 === "undefined")
{
  alert("cp3");
}

if(t2 === undefined) // fails as t2 is never declared
{
  alert("cp4");
}

quelle
1
Okay, aber die Variable ist in diesem Fall deklariert. Worum geht es also?
Ry-
Persönlich finde ich es foo === undefinedgefährlich zu benutzen. Dadurch schlägt Ihr Code unter denselben Bedingungen fehl, die Sie verhindern wollten.
Ich spreche über das Argument zu der fraglichen Funktion. Siehe auch meinen anderen Kommentar .
Ry-
1
Warum wird dies herabgestuft? Der allererste Satz ist eine korrekte und wichtige Unterscheidung!
Izkata
1
@Izkata: weil es keine Erklärung für die ursprüngliche Aussage gibt. foo === undefinedist in der Situation des OP durchaus akzeptabel (vorausgesetzt, es undefinedwurde nicht überschrieben). Die Antwort erklärt auch nicht, warum !== anstelle von verwendet werden sollte !=.
Matt
1

Der einfache Weg, um Ihren Test durchzuführen, ist:

function (data) {
    if (data) { // check if null, undefined, empty ...
        // some code here
    }
}
Kadiri
quelle
5
Ist dieser Test nicht kontextabhängig? Ich meine, wenn der erwartete Typ für dataeine Zeichenfolge ist, gibt dieser Test für leere Zeichenfolgen false zurück, was möglicherweise angemessen ist oder nicht (die Funktion möchte möglicherweise auf irgendeine Weise mit der leeren Zeichenfolge umgehen).
Afsantos
5
Außer wenn "Daten" den Wert ""oder 0oder NaN(oder andere) haben, wird der "Wenn" -Block übersprungen; was die Absicht von OP sein kann oder nicht.
Maerics
Sorry @afsantos, ich habe deinen Kommentar nicht gesehen. Wenn du falsch werden willst, wenn Daten undefiniert sind, null ... außer wenn das Datum leer ist, musst du eine andere var toTest = data erstellen . mit einem anderen Test nach dem ersten wie: if (toTest == "") {// etwas Code hier}
Kadiri
-5
var a;
alert(a); //Value is undefined

var b = "Volvo"; 
alert(b); //Value is Volvo

var c = null;
alert(c); //Value is null
Überlauf
quelle
4
Bitte fügen Sie eine Erklärung hinzu, was dies bedeuten soll.
Ry-
Dies gilt nicht wirklich überprüfen zu null.
user4642212