variabile === undefined vs. typeof variable === “undefined”

Le linee guida di stile jQuery Core suggeriscono due diversi modi per verificare se una variabile è definita.

  • Variabili globali: typeof variable === "undefined"
  • Variabili locali: variable === undefined
  • Proprietà: object.prop === undefined

Perché jQuery usa un approccio per le variabili globali e un altro per i locali e le proprietà?

Per le variabili non dichiarate, typeof foo restituirà la stringa letterale "undefined" , mentre il controllo dell’id quadro foo === undefined attiverà l’errore “foo non è definito” .

Per le variabili locali (che sai essere dichiarate da qualche parte), non si verificherà tale errore, quindi il controllo dell’id quadro.

Mi limiterei a usare typeof foo === "undefined" ovunque. Ciò non può mai andare storto.

Immagino il motivo per cui jQuery consiglia i due diversi metodi è che definiscono la propria variabile undefined all’interno della funzione in cui il codice jQuery vive, quindi all’interno di quella funzione undefined è al sicuro da manomissioni esterne. Immagino anche che qualcuno da qualche parte abbia messo a confronto i due diversi approcci e scoperto che foo === undefined è più veloce e quindi ha deciso che è la strada da percorrere. [AGGIORNAMENTO: come notato nei commenti, il confronto con undefined è anche leggermente più breve, che potrebbe essere una considerazione.] Tuttavia, il guadagno in situazioni pratiche sarà del tutto insignificante: questo controllo non sarà mai e poi mai un qualsiasi collo di bottiglia, e ciò che si perde è significativo: la valutazione di una proprietà di un object host per il confronto può generare un errore mentre un controllo typeof non lo farà mai.

Ad esempio, in IE viene utilizzato quanto segue per l’analisi di XML:

 var x = new ActiveXObject("Microsoft.XMLDOM"); 

Per verificare se ha un metodo loadXML modo sicuro:

 typeof x.loadXML === "undefined"; // Returns false 

D’altra parte:

 x.loadXML === undefined; // Throws an error 

AGGIORNARE

Un altro vantaggio del controllo typeof che ho dimenticato di menzionare è che funziona anche con variabili non dichiarate, che il controllo foo === undefined no, e in effetti lancia un ReferenceError . Grazie a @LinusKleen per avermelo ricordato. Per esempio:

 typeof someUndeclaredVariable; // "undefined" someUndeclaredVariable === undefined; // throws a ReferenceError 

In conclusione: usa sempre il controllo typeof .

Ancora un altro motivo per usare il typeof-variant: undefined può essere ridefinito.

 undefined = "foo"; var variable = "foo"; if (variable === undefined) console.log("eh, what?!"); 

Il risultato della typeof variable non può.

Aggiornamento : si noti che questo non è il caso di ES5.

Chi è interessato al guadagno di prestazioni della variable === undefined , può dare un’occhiata qui, ma sembra essere solo un’ottimizzazione del cromo.

Perché undefined non è sempre dichiarato, ma jQuery dichiara undefined nella sua funzione principale. Quindi usano internamente il valore undefined sicuro, ma fuori, usano lo stile typeof per essere sicuri.

Per le variabili locali, il controllo con localVar === undefined funzionerà perché devono essere stati definiti da qualche parte nell’ambito locale o non saranno considerati locali.

Per le variabili che non sono locali e non sono definite ovunque, il controllo someVar === undefined genera un’eccezione: Uncaught ReferenceError: j non è definito

Ecco un codice che chiarirà quello che sto dicendo sopra. Si prega di prestare attenzione ai commenti in linea per maggiore chiarezza .

 function f (x) { if (x === undefined) console.log('x is undefined [x === undefined].'); else console.log('x is not undefined [x === undefined.]'); if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].'); else console.log('x is not undefined [typeof(x) === \'undefined\'].'); // This will throw exception because what the hell is j? It is nowhere to be found. try { if (j === undefined) console.log('j is undefined [j === undefined].'); else console.log('j is not undefined [j === undefined].'); } catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');} // However this will not throw exception if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.'); else console.log('j is not undefined [typeof(x) === \'undefined\'].'); }; 

Se chiamiamo il codice di cui sopra in questo modo:

 f(); 

L’output sarebbe questo:

 x is undefined [x === undefined]. x is undefined [typeof(x) === 'undefined']. Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code. j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw. 

Se chiamiamo il codice sopra come questi (con qualsiasi valore in realtà):

 f(null); f(1); 

L’output sarà:

 x is not undefined [x === undefined]. x is not undefined [typeof(x) === 'undefined']. Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code. j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw. 

Quando si effettua il controllo in questo modo: typeof x === 'undefined' , si sta essenzialmente chiedendo questo: Si prega di verificare se la variabile x esiste (è stata definita) da qualche parte nel codice sorgente. (più o meno). Se conosci C # o Java, questo tipo di controllo non viene mai eseguito perché, se non esiste, non verrà compilato.

<== Fiddle Me ==>

typeof a === 'undefined' è più veloce di a === 'undefined' di circa 2 volte sul nodo v6.9.1.