Come verificare la presenza di “non definito” in JavaScript?

Qual è il modo più appropriato per verificare se una variabile non è definita in JavaScript? Ho visto diversi modi possibili:

if (window.myVariable) 

O

 if (typeof(myVariable) != "undefined") 

O

 if (myVariable) //This throws an error if undefined. Should this be in Try/Catch? 

Se sei interessato a scoprire se una variabile è stata dichiarata indipendentemente dal suo valore, usare l’operatore in è la maniera più sicura. Considera questo esempio.

 // global scope var theFu; // theFu has been declared, but its value is undefined typeof theFu; // "undefined" 

Ma questo potrebbe non essere il risultato previsto per alcuni casi, dal momento che la variabile o la proprietà è stata dichiarata, ma solo non inizializzata. Utilizzare l’operatore in per un controllo più robusto.

 "theFu" in window; // true "theFoo" in window; // false 

Se sei interessato a sapere se la variabile non è stata dichiarata o ha un valore undefined , usa l’operatore typeof .

 if (typeof myVar != 'undefined') 

L’operatore typeof è garantito per restituire una stringa. I confronti diretti contro undefined sono fastidiosi poiché un undefined può essere sovrascritto.

 window.undefined = "omg"; "omg" == undefined // true 

Come ha sottolineato @CMS, questo è stato corretto in ECMAScript 5th ed. E undefined non è scrivibile.

if (window.myVar) includerà anche questi valori falsy, quindi non è molto robusto:

 falso
 0
 ""
 NaN
 nullo
 non definito

Grazie a @CMS per aver segnalato che il tuo terzo caso – if (myVariable) può anche generare un errore in due casi. Il primo è quando la variabile non è stata definita e lancia un ReferenceError .

 // abc was never declared. if (abc) { // ReferenceError: abc is not defined } 

L’altro caso è quando la variabile è stata definita, ma ha una funzione getter che genera un errore quando viene invocata. Per esempio,

 // or it's a property that can throw an error Object.defineProperty(window, "myVariable", { get: function() { throw new Error("W00t?"); }, set: undefined }); if (myVariable) { // Error: W00t? } 

Io personalmente uso

 myVar === undefined 

Avvertenza: si prega di notare che === è usato su == e che myVar è stato precedentemente dichiarato (non definito ).


Non mi piace il typeof myVar === "undefined" . Penso che sia lungo e inutile. (Posso ottenere lo stesso risultato con meno codice.)

Ora alcune persone si lamenteranno per il dolore quando leggono questo, urlando: “Aspetta, WAAITTT !!! undefined può essere ridefinito!”

Freddo. Lo so. Inoltre, la maggior parte delle variabili in Javascript può essere ridefinita. Non dovresti mai usare un identificatore integrato che possa essere ridefinito?

Se segui questa regola, fa bene a te: non sei un ipocrita.

Il fatto è che, per fare un sacco di lavoro reale in JS, gli sviluppatori devono affidarsi a identificatori ridefinibili per essere quello che sono. Non sento le persone che mi dicono che non dovrei usare setTimeout perché qualcuno può farlo

 window.setTimeout = function () { alert("Got you now!"); }; 

In conclusione, l’argomento “può essere ridefinito” per non usare un raw === undefined è fasullo.

(Se hai ancora paura di ridefinire un undefined , perché stai integrando ciecamente codice di libreria non testato nella tua base di codice? O ancora più semplice: uno strumento di sfilacciamento.)


Inoltre, come l’approccio typeof , questa tecnica può “rilevare” le variabili non dichiarate:

 if (window.someVar === undefined) { doSomething(); } 

Ma entrambe queste tecniche perdono nella loro astrazione. Vi esorto a non usare questo o addirittura

 if (typeof myVar !== "undefined") { doSomething(); } 

Prendere in considerazione:

 var iAmUndefined; 

Per capire se la variabile è dichiarata o meno, potrebbe essere necessario ricorrere all’operatore in. (In molti casi, puoi semplicemente leggere il codice O_o).

 if ("myVar" in window) { doSomething(); } 

Ma aspetta! C’è più! Cosa succede se qualche prototipo di magia della catena sta accadendo …? Ora nemmeno l’operatore superiore in non è sufficiente. (Ok, ho finito qui per questa parte eccetto per dire che per il 99% delle volte, === undefined (e **** cough **** typeof ) funziona bene. Se ti interessa davvero, puoi leggi di questo argomento da solo.)

Usare typeof è la mia preferenza. Funzionerà quando la variabile non è mai stata dichiarata, diversamente da qualsiasi confronto con gli operatori == o === o la coercizione di tipo che usa if . ( undefined , a differenza di null , può anche essere ridefinito negli ambienti ECMAScript 3, rendendolo inaffidabile per il confronto, sebbene quasi tutti gli ambienti comuni ora siano compatibili con ECMAScript 5 o successivi).

 if (typeof someUndeclaredVariable == "undefined") { // Works } if (someUndeclaredVariable === undefined) { // Throws an error } 

Devi usare typeof .

 if (typeof something != "undefined") { // ... } 

Se non è definito, non sarà uguale a una stringa che contiene i caratteri “non definito”, in quanto la stringa non è indefinita.

Puoi controllare il tipo di variabile:

 if (typeof(something) != "undefined") ... 

A volte non devi nemmeno controllare il tipo. Se il valore della variabile non può essere valutato come falso quando è impostato (ad esempio se si tratta di una funzione), puoi semplicemente valutare la variabile. Esempio:

 if (something) { something(param); } 

Alcuni scenari che illustrano i risultati delle varie risposte: http://jsfiddle.net/drzaus/UVjM4/

(Si noti che l’uso di var per i test fa la differenza quando si trova in un wrapper con scope)

Codice di riferimento:

 (function(undefined) { var definedButNotInitialized; definedAndInitialized = 3; someObject = { firstProp: "1" , secondProp: false // , undefinedProp not defined } // var notDefined; var tests = [ 'definedButNotInitialized in window', 'definedAndInitialized in window', 'someObject.firstProp in window', 'someObject.secondProp in window', 'someObject.undefinedProp in window', 'notDefined in window', '"definedButNotInitialized" in window', '"definedAndInitialized" in window', '"someObject.firstProp" in window', '"someObject.secondProp" in window', '"someObject.undefinedProp" in window', '"notDefined" in window', 'typeof definedButNotInitialized == "undefined"', 'typeof definedButNotInitialized === typeof undefined', 'definedButNotInitialized === undefined', '! definedButNotInitialized', '!! definedButNotInitialized', 'typeof definedAndInitialized == "undefined"', 'typeof definedAndInitialized === typeof undefined', 'definedAndInitialized === undefined', '! definedAndInitialized', '!! definedAndInitialized', 'typeof someObject.firstProp == "undefined"', 'typeof someObject.firstProp === typeof undefined', 'someObject.firstProp === undefined', '! someObject.firstProp', '!! someObject.firstProp', 'typeof someObject.secondProp == "undefined"', 'typeof someObject.secondProp === typeof undefined', 'someObject.secondProp === undefined', '! someObject.secondProp', '!! someObject.secondProp', 'typeof someObject.undefinedProp == "undefined"', 'typeof someObject.undefinedProp === typeof undefined', 'someObject.undefinedProp === undefined', '! someObject.undefinedProp', '!! someObject.undefinedProp', 'typeof notDefined == "undefined"', 'typeof notDefined === typeof undefined', 'notDefined === undefined', '! notDefined', '!! notDefined' ]; var output = document.getElementById('results'); var result = ''; for(var t in tests) { if( !tests.hasOwnProperty(t) ) continue; // bleh try { result = eval(tests[t]); } catch(ex) { result = 'Exception--' + ex; } console.log(tests[t], result); output.innerHTML += "\n" + tests[t] + ": " + result; } })(); 

E risultati:

 definedButNotInitialized in window: true definedAndInitialized in window: false someObject.firstProp in window: false someObject.secondProp in window: false someObject.undefinedProp in window: true notDefined in window: Exception--ReferenceError: notDefined is not defined "definedButNotInitialized" in window: false "definedAndInitialized" in window: true "someObject.firstProp" in window: false "someObject.secondProp" in window: false "someObject.undefinedProp" in window: false "notDefined" in window: false typeof definedButNotInitialized == "undefined": true typeof definedButNotInitialized === typeof undefined: true definedButNotInitialized === undefined: true ! definedButNotInitialized: true !! definedButNotInitialized: false typeof definedAndInitialized == "undefined": false typeof definedAndInitialized === typeof undefined: false definedAndInitialized === undefined: false ! definedAndInitialized: false !! definedAndInitialized: true typeof someObject.firstProp == "undefined": false typeof someObject.firstProp === typeof undefined: false someObject.firstProp === undefined: false ! someObject.firstProp: false !! someObject.firstProp: true typeof someObject.secondProp == "undefined": false typeof someObject.secondProp === typeof undefined: false someObject.secondProp === undefined: false ! someObject.secondProp: true !! someObject.secondProp: false typeof someObject.undefinedProp == "undefined": true typeof someObject.undefinedProp === typeof undefined: true someObject.undefinedProp === undefined: true ! someObject.undefinedProp: true !! someObject.undefinedProp: false typeof notDefined == "undefined": true typeof notDefined === typeof undefined: true notDefined === undefined: Exception--ReferenceError: notDefined is not defined ! notDefined: Exception--ReferenceError: notDefined is not defined !! notDefined: Exception--ReferenceError: notDefined is not defined 
 if (typeof foo == 'undefined') { // Do something }; 

Nota che il confronto rigoroso ( !== ) non è necessario in questo caso, dal momento che typeof restituirà sempre una stringa.

In questo articolo ho letto che framework come Underscore.js usano questa funzione:

 function isUndefined(obj){ return obj === void 0; } 

Il modo più affidabile che conosca per il controllo di undefined è l’utilizzo di void 0 .

Questo è compatibile con i browser più vecchi e nuovi, allo stesso modo, e non può essere sovrascritto come window.undefined può in alcuni casi.

 if( myVar === void 0){ //yup it's undefined } 

Personalmente, uso sempre quanto segue:

 var x; if( x === undefined) { //Do something here } else { //Do something else here } 

La proprietà window.undefined non è scrivibile in tutti i browser moderni (JavaScript 1.8.5 o successivo). Dalla documentazione di Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined , vedo questo: un motivo per usare typeof () è che non genera un errore se la variabile non è stata definita.

Preferisco avere l’approccio di usare

 x === undefined 

perché fallisce e scoppia in faccia piuttosto che passare / fallire silenziosamente se x non è stato dichiarato prima. Questo mi avvisa che x non è dichiarato. Credo che tutte le variabili usate in JavaScript debbano essere dichiarate.

Aggiornamento 2018-07-25

Sono trascorsi quasi cinque anni da quando questo post è stato realizzato per la prima volta, e JavaScript ha fatto molta strada. Nel ripetere i test nel post originale, non ho riscontrato differenze consistenti tra i seguenti metodi di test:

  • abc === undefined
  • abc === void 0
  • typeof abc == 'undefined'
  • typeof abc === 'undefined'

Anche quando ho modificato i test per impedire a Chrome di ottimizzarli, le differenze erano insignificanti. Come tale, ora consiglierei abc === undefined per chiarezza.

Contenuti rilevanti di chrome://version :

  • Google Chrome: 67.0.3396.99 (Build ufficiale) (64-bit) (coorte: stabile)
  • Revisione: a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs / branch-heads / 3396 @ {# 790}
  • Sistema operativo: Windows
  • JavaScript: V8 6.7.288.46
  • Agente utente: Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, come Gecko) Chrome / 67.0.3396.99 Safari / 537.36

Post originale 2013-11-01

In Google Chrome, il seguente è stato sempre leggermente più veloce di un test di tipo:

 if (abc === void 0) { // Undefined } 

La differenza era trascurabile. Tuttavia, questo codice è più conciso, e più chiaro a colpo d’occhio a qualcuno che sa cosa vuol dire void 0 . Nota, tuttavia, che abc deve ancora essere dichiarato.

Sia typeof che void erano significativamente più veloci rispetto al confronto diretto con undefined . Ho utilizzato il seguente formato di test nella console degli sviluppatori di Chrome:

 var abc; start = +new Date(); for (var i = 0; i < 10000000; i++) { if (TEST) { void 1; } } end = +new Date(); end - start; 

I risultati sono stati i seguenti:

 Test: | abc === undefined abc === void 0 typeof abc == 'undefined' ------+--------------------------------------------------------------------- x10M | 13678 ms 9854 ms 9888 ms x1 | 1367.8 ns 985.4 ns 988.8 ns 

Si noti che la prima riga è in milli secondi, mentre la seconda riga è in nano secondi. Una differenza di 3,4 nanosecondi non è nulla. I tempi erano abbastanza consistenti nei test successivi.

Poiché nessuna delle altre risposte mi ha aiutato, suggerisco di farlo. Ha funzionato per me in Internet Explorer 8:

 if (typeof variable_name.value === 'undefined') { // variable_name is undefined } 
 // x has not been defined before if (typeof x === 'undefined') { // Evaluates to true without errors. // These statements execute. } if (x === undefined) { // Throws a ReferenceError } 

Al contrario della risposta di @Thomas Eding:

Se dimentico di dichiarare myVar nel mio codice, myVar is not defined .

Facciamo un esempio reale:

Ho un nome variabile, ma non sono sicuro che sia stato dichiarato da qualche parte o meno.

Quindi la risposta di @ Anurag aiuterà:

 var myVariableToCheck = 'myVar'; if (window[myVariableToCheck] === undefined) console.log("Not declared or declared, but undefined."); // Or you can check it directly if (window['myVar'] === undefined) console.log("Not declared or declared, but undefined."); 
  var x; if (x === undefined) { alert ("I am declared, but not defined.") }; if (typeof y === "undefined") { alert ("I am not even declared.") }; /* One more thing to understand: typeof ==='undefined' also checks for if a variable is declared, but no value is assigned. In other words, the variable is declared, but not defined. */ // Will repeat above logic of x for typeof === 'undefined' if (x === undefined) { alert ("I am declared, but not defined.") }; /* So typeof === 'undefined' works for both, but x === undefined only works for a variable which is at least declared. */ /* Say if I try using typeof === undefined (not in quotes) for a variable which is not even declared, we will get run a time error. */ if (z === undefined) { alert ("I am neither declared nor defined.") }; // I got this error for z ReferenceError: z is not defined 

Lo uso come parametro di funzione e lo escludo nell’esecuzione della funzione in questo modo ottengo il “reale” indefinito. Sebbene richieda di inserire il codice in una funzione. Ho trovato questo durante la lettura della fonte jQuery.

 undefined = 2; (function (undefined) { console.log(undefined); // prints out undefined // and for comparison: if (undeclaredvar === undefined) console.log("it works!") })() 

Ovviamente potresti usare solo typeof . Ma tutto il mio codice è in genere all’interno di una funzione di contenimento comunque, quindi l’utilizzo di questo metodo probabilmente mi consente di risparmiare qualche byte qua e là.