Controllo null JavaScript


170

Mi sono imbattuto nel seguente codice:

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

Sono un po 'nuovo di JavaScript, ma, da altre domande che ho letto qui, ho l'impressione che questo codice non abbia molto senso.


In particolare, questa risposta afferma che

Riceverai un errore se accedi a una variabile non definita in qualsiasi contesto diverso da typeof.

Aggiornamento: la (citazione della) risposta sopra potrebbe essere fuorviante. Dovrebbe dire «una variabile non dichiarata» , invece di «una variabile non definita» .

Come ho scoperto, nelle risposte di Ryan ♦ , maerics e nwellnhof , anche quando non viene fornito alcun argomento a una funzione, le sue variabili per gli argomenti vengono sempre dichiarate. Questo fatto dimostra inoltre che il primo elemento nell'elenco seguente è errato.


Da quanto ho capito, si possono verificare i seguenti scenari:

  • La funzione è stata chiamata senza argomenti, creando così datauna variabile non definita e generando un errore data != null.

  • La funzione è stata chiamata specificamente con null(o undefined), come argomento, nel qual caso data != nullprotegge già il codice interno, rendendolo && data !== undefinedinutile.

  • La funzione è stata chiamata con un argomento non nullo, nel qual caso passerà banalmente sia data != null e data !== undefined .

D: La mia comprensione è corretta?


Ho provato quanto segue, nella console di Firefox:

--
[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

Non riesco a capire un caso in cui il data !== undefined dopo data != null potrebbe essere di qualche utilità.


9
Basta usare if (data). È un modo mnemonico Javascript per verificare se la datavariabile viene valutata come vera. undefined, null, False, 0, stringa vuota, array vuoto e oggetto (?) Senza proprietà restituisce false, il resto è vero.
J0HN,

20
@ J0HN - L'uso if(data)significherebbe che non può passare falseo 0come valori per data.
techfoobar,

@ J0HN Inoltre, la stessa risposta che cito afferma anche che:, if(typeof someUndefVar == whatever) -- workse if(someUnderVar) -- error.
afsantos,

2
Probabilmente dovrebbe essere data !== null && data !== undefined, che è equivalente a data != nullcui è equivalente data != undefined. La prima forma tende a essere favorita in quanto è più esplicita riguardo alle condizioni, mentre sarebbe facile trascurarle entrambe nulle undefinedvengono verificate con le due condizioni successive.
zzzzBov,

2
A proposito, i test espliciti per l' undefinedIMO sono un odore di codice. Non è una parola chiave protetta come null, è una variabile che sembra essere indefinita. Questo è completamente valido e sta per violare il codice:undefined = 1
Izkata,

Risposte:


106

Una "variabile non definita" è diversa dal valore undefined.

Una variabile non definita:

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

Una variabile con il valore undefined:

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

Quando una funzione accetta un argomento, quell'argomento viene sempre dichiarato anche se il suo valore è undefined, e quindi non ci sarà alcun errore. Hai ragione, != nullseguito !== undefineddall'essere inutile, però.


32
data !== null && data !== undefinedavrebbe senso, però.
bfavaretto,

@bfavaretto: Sì, quindi potrebbe effettivamente essere un errore di battitura. Ma non sai mai ...: D
Ry-

1
Proprio come pensavo, grazie per il chiarimento. Inoltre, non credo sia un errore di battitura. Ho eseguito un find-and-count in tutto lo script e ho trovato 10 occorrenze, quindi ... immagino che anche l'autore abbia bisogno di chiarimenti su questo.
afsantos,

2
Gratta il mio commento sopra: in realtà, data != nullverificherei entrambi nulle undefined(ma, cosa interessante, solo per nulle undefined, e non gli altri valori falsi).
bfavaretto,

90

In JavaScript, nullè un oggetto singleton speciale che è utile per segnalare "nessun valore". Puoi testarlo per confronto e, come al solito in JavaScript, è una buona pratica usare l' ===operatore per evitare confusione di tipo confuso:

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

Come menziona @rynah, "undefined" è un po 'confuso in JavaScript. Tuttavia, è sempre sicuro verificare se la typeof(x)stringa è "non definita", anche se "x" non è una variabile dichiarata:

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

Inoltre, le variabili possono avere il "valore indefinito" se non sono inizializzate:

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

Mettendo tutto insieme, il tuo controllo dovrebbe assomigliare a questo:

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

Tuttavia, poiché la variabile "dati" è sempre definita poiché si tratta di un parametro di funzione formale, l'utilizzo dell'operatore "typeof" non è necessario e si può tranquillamente confrontare direttamente con il "valore indefinito".

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

Questo frammento equivale a dire "se la funzione è stata chiamata con un argomento che è definito e non è nullo ..."


5
Perché dovrebbe apparire così, però? != nullsarà vero per tutti i valori tranne nulle undefined, e siamo sicuri che questa variabile sia dichiarata. typeofin altre situazioni può anche essere pericoloso: cosa succede se si digita male il nome della variabile? Questo può rimanere inosservato per molto tempo perché non c'è errore.
Ry-

@maerics Quindi, se ho seguito correttamente la vostra risposta, in un controllo di nulla come lo scenario di cui sopra, non sarebbe utilizzare !=a tutti, solo confronto rigoroso, !==?
afsantos,

@rynah: non presumo di conoscere abbastanza la soluzione complessiva di OP per sapere se un test nullo è appropriato o no, ma ho modificato per menzionare il fatto che l'uso di "typeof" non è necessario.
Maerics,

@afsantos: in realtà non credo che molti valori (qualsiasi?) si convertiranno in null; tuttavia, è consigliabile utilizzare il confronto rigoroso ( ===) a meno che tu non sappia davvero cosa stai facendo e desideri un confronto dopo la conversione ( ==).
Maerics,

1
@Izkata: elimina qualsiasi libreria che tenta di ridefinire undefined. Inoltre, Safari su iPad non lo farà in nessun caso. Non puoi nemmeno delete window.undefined.
Ry-

10

Nel tuo caso usa data==null(che è vero SOLO per null e indefinito - al secondo fuoco dell'immagine su righe / colonne null-indefinito)

Qui hai tutto ( src ):

Se

inserisci qui la descrizione dell'immagine

== (la sua negazione ! = )

inserisci qui la descrizione dell'immagine

=== (la sua negazione ! == )

inserisci qui la descrizione dell'immagine


8

D: La funzione è stata chiamata senza argomenti, rendendo i dati una variabile indefinita e generando un errore sui dati! = Null.

A: Sì, datasarà impostato su indefinito. Vedere la sezione 10.5 Dichiarazione vincolante Istantanea della specifica. Ma l'accesso a un valore non definito non genera un errore. Probabilmente stai confondendo questo con l'accesso a una variabile non dichiarata in modalità rigorosa che genera un errore.

D: La funzione è stata chiamata specificamente con null (o non definito), come argomento, nel qual caso data! = Null protegge già il codice interno, rendendo && data! == undefined inutili.

D: La funzione è stata chiamata con un argomento non nullo, nel qual caso passerà banalmente entrambi i dati! = Null e data! == undefined.

A: Corretto. Si noti che i seguenti test sono equivalenti:

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

Vedere la sezione 11.9.3 L' algoritmo di confronto sull'uguaglianza astratta e la sezione 11.9.6. L'algoritmo di confronto sull'uguaglianza rigorosa della specifica.


Non stavo confondendo con le variabili non dichiarate, non sapevo davvero come funzionasse quando non venivano forniti argomenti. Ero convinto che datanon esistesse affatto, invece di essere impostato su undefined. Apprezzo il chiarimento e quei riferimenti mi hanno aiutato a capire meglio come funzionano entrambe le uguaglianze.
afsantos,

3

Penso che testare le variabili per valori che non ti aspetti non sia una buona idea in generale. Perché il tuo test può essere considerato come scrivere una lista nera di valori proibiti. E se dimenticassi di elencare tutti i valori proibiti? Qualcuno, anche tu, può decifrare il tuo codice passando un valore inaspettato. Quindi un approccio più appropriato è qualcosa come la whitelisting: testare le variabili solo per i valori previsti, non inaspettati. Ad esempio, se si prevede che il valore dei dati sia una stringa, anziché questo:

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

fai qualcosa del genere:

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
  } 
}

2

typeof foo === "undefined"è diverso da foo === undefined, non confonderli mai. typeof foo === "undefined"è ciò di cui hai veramente bisogno. Inoltre, utilizzare !==al posto di!=

Quindi la dichiarazione può essere scritta come

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

Modificare:

Non è possibile utilizzare foo === undefinedper variabili non dichiarate.

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");
}

1
Va bene, ma la variabile è dichiarata in questo caso, quindi qual è il problema?
Ry-

Personalmente, trovo foo === undefinedpericoloso da usare. Rende il tuo codice non riuscito per la stessa condizione che stavi cercando di prevenire.

Sto parlando dell'argomento alla funzione in questione. Vedi anche il mio altro commento .
Ry-

1
Perché questo viene annullato? La prima frase è una distinzione corretta e importante !
Izkata,

1
@Izkata: perché non ci sono spiegazioni per la dichiarazione iniziale. foo === undefinedè perfettamente accettabile nella situazione del PO (supponendo che undefinednon sia stato ignorato). La risposta non riesce anche a spiegare perché !== dovrebbe essere usato al posto di !=.
Matt,

1

Il modo semplice per eseguire il test è:

function (data) {
    if (data) { // check if null, undefined, empty ...
        // some code here
    }
}

5
Questo test non dipende dal contesto? Voglio dire, se il tipo previsto per dataè una stringa, questo test restituisce false su stringhe vuote, che potrebbero essere o non essere appropriate (la funzione potrebbe voler gestire la stringa vuota in qualche modo).
afsantos,

5
Tranne che se "dati" ha il valore ""o 0o NaN(o altri) il blocco "if" verrà ignorato; che può essere o meno l'intento di OP.
Maerics,

Spiacente @afsantos, non ho visto il tuo commento, se vuoi diventare falso quando i dati non sono definiti, null ... tranne quando la data è vuota, dovrai creare un'altra var toTest = data; con un altro test dopo il primo come: if (toTest == "") {// qualche codice qui}
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

4
Per favore, aggiungi qualche spiegazione su cosa dovrebbe significare.
Ry-

Questo in realtà non controlla per null.
user4642212
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.