typeof! == “undefined” vs.! = null


491

Vedo spesso il codice JavaScript che controlla i parametri non definiti ecc. In questo modo:

if (typeof input !== "undefined") {
    // do stuff
}

Questo sembra un po 'dispendioso, dal momento che comporta sia una ricerca del tipo che un confronto di stringhe, per non parlare della sua verbosità. È necessario perché undefinedpotrebbe essere rinominato, però.

La mia domanda è: in che
modo questo codice è migliore di questo approccio:

if (null != input) {
    // do stuff
}

Per quanto ne so, non puoi ridefinire null, quindi non si romperà inaspettatamente. E, a causa della coercizione del tipo !=dell'operatore, questo verifica sia per undefinede null... che spesso è esattamente ciò che si desidera (ad es. Per parametri di funzione opzionali).

Tuttavia, questo modulo non sembra molto diffuso e fa persino gridare a JSLint per aver usato l' !=operatore malvagio .

Perché questo è considerato un cattivo stile?


13
@ Marcel, non c'è vera differenza, ma ci sono due ragioni per farlo. Uno, è che per alcuni è più chiaro da leggere. E la seconda ragione è che impedisce la sovrascrittura accidentale di una variabile. Hai mai fatto questo: if (foo = "value") quando intendi fare un confronto. Se hai l'abitudine di invertire la variabile, nell'operatore di assegnazione / confronto, non avrai questo problema.
Layke,

29
Per alcuni (incluso me) questo è in realtà più difficile da leggere. Inoltre, la maggior parte degli IDE ti avvisano di assegnazioni accidentali. Ma uso ancora questo modulo se la variabile confrontata è molto lunga. YMMV.
johndodo,

15
@MarcelKorpel Questo si chiama "Yoda condition": umumble.com/blogs/Programming/321
kol

55
È più difficile da leggere. Non si dice "Non vuota è la bottiglia".
Noel Abrahams,

11
if (null != input)è solo "Yoda Speak" per chi parla inglese (Di uno che sono .... uuammmmm) quindi se si equivalgono alla stessa cosa è davvero solo una semantica. A PARER MIO.
webLacky3rdClass

Risposte:


710

typeof è più sicuro in quanto consente all'identificatore di non essere mai stato dichiarato prima:

if(typeof neverDeclared === "undefined") // no errors

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined

3
if ((typeof neverDeclared! == "undefined") && (neverDeclared! == null)) {return true; } else {return false; }
Anthony DiSanti,

88
Utilizzare === nel confronto con null / non definito.
MyGGaN,

47
@MyGGaN solo se vuoi distinguere tra i due. In molti casi, ==può essere migliore, perché verifica sia null che indefinito.
seanmonstar,

10
Non riesco a trovare alcuna differenza tra typeof somevar == 'undefined' e typeof somevar === 'undefined', perché typeof restituisce sempre stringa. Per null restituirà 'oggetto'. O potrebbe essere che mi sbaglio?
TomTom,

2
Credo che il commento di @ TomTom sia il punto cruciale del problema: non riesco a capire perché si utilizzino gli operatori !==o ===quando si confronta un valore il cui tipo è noto per essere una stringa.
Nicolas Rinaudo,

49

Se la variabile viene dichiarata (o con la varparola chiave, come argomento di funzione o come variabile globale), penso che il modo migliore per farlo sia:

if (my_variable === undefined)

jQuery lo fa, quindi è abbastanza buono per me :-)

Altrimenti, dovrai usare typeofper evitare a ReferenceError.

Se prevedi di ridefinire undefined, puoi racchiudere il codice in questo modo:

(function(undefined){
    // undefined is now what it's supposed to be
})();

O ottenerlo tramite l' voidoperatore:

const undefined = void 0;
// also safe

1
Se undefined è già stato definito, allora non lo passeresti alla tua funzione anonima attraverso un parametro chiamato indefinito, senza ottenere nulla?
Anthony DiSanti,

20
@Anthony DiSanti: No, undefinedè il nome assegnato al parametro della funzione, non il suo valore. Nulla viene passato alla funzione, il che significa che il valore del primo parametro non è definito.
Joey Adams,

3
Ah, mio ​​errore, grazie per il seguito. Ho rimosso il mio voto in basso, mi dispiace per quello.
Anthony DiSanti,

2
Perché scrivere un'eccezione per gestire l'essere indefinito dichiarato da un altro sviluppatore quando puoi semplicemente farlo correttamente per cominciare? jQuery racchiude la funzione anonima iniziale mostrata nella funzione per garantire che non sia stato definito undefined e per ridurre le dimensioni minime. In poche parole, se può dare risultati inaspettati per farlo in questo modo, perché rischiarlo per una programmazione pigra per evitare la battitura (typeof variabile === 'undefined'). E se volessimo (typeof variabile === 'oggetto') dovremmo fornire una variabile predefinita che sia anche un oggetto in modo da poter fare (variabile === oggetto)?
Fyrye,

28

buon modo:

if(typeof neverDeclared == "undefined") //no errors

Ma il modo migliore è controllare tramite:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings

6
var undefined = function () {}; if (typeof neverDeclared === typeof undefined); neverDecalred! = 'function'; jsfiddle.net/hbPZ5 return typeof var; restituisce una stringa. Nessun errore o stringa ma non fornirà sempre i risultati previsti. Gli sviluppatori concessi non dovrebbero dichiarare indefiniti, ma ci sono alcuni framework e librerie che lo fanno.
Fyrye,

1
Uso principalmente if (typeof neverDeclared === typeof undefined) { ma Lint genera un errore. "Si aspettava una stringa e invece ha visto 'typeof'." Come aggireresti questo errore? Dovremmo sottometterci alle richieste di Lint e usare invece il "buon modo"?
Ayelis,

2
@fyrye Conoscete qualche libreria / framework JavaScript che muta effettivamente non definito? So che è possibile; ma vorrei trovare un esempio nel selvaggio di "Qui è dove potresti incontrare questo cattivo GNU!"
bigtunacan,

4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich,

1
È soggetto a errori, perché in realtà stai solo facendo affidamento su una determinata variabile ("non definita") che non viene definita. Che può essere falso, come hanno mostrato altri post. Puoi sempre fare if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {ma è piuttosto lungo.
Pierre-Olivier Vares,

12

Non dovresti davvero preoccuparti di essere rinominato indefinito. Se qualcuno rinomina indefinito, avrai molti più problemi di pochi se i controlli falliscono. Se vuoi davvero proteggere il tuo codice, avvolgilo in un IFFE (espressione di funzione immediatamente invocata) in questo modo:

(function($, Backbone, _, undefined) {
    //undefined is undefined here.
})(jQuery, Backbone, _);

Se stai lavorando con variabili globali (che sono già sbagliate) in un ambiente browser, verificherei che non siano definite in questo modo:

if(window.neverDefined === undefined) {
    //Code works
}

Dato che le variabili globali fanno parte dell'oggetto Window, puoi semplicemente controllare contro indefinito invece di eseguire il casting su una stringa e confrontarne le stringhe.

Inoltre, perché le variabili non sono definite? Ho visto un sacco di codice in cui controllano l'esistenza di una variabile ed eseguono un'azione basata su quella. Non ho visto una volta dove questo approccio è stato corretto.


1
La convalida dell'input e il controllo delle dipendenze sono entrambi buoni motivi per usarlo. Se ho file Javascript che dipendono da altri file che sono stati caricati o che sono stati dichiarati oggetti init, allora è utile testare oggetti o proprietà su cui un file dipende da indefinito e generare una bella eccezione invece di lasciare che lo script fallisca da qualche parte imprevedibile.
AmericanUmlaut,

Sembra che potresti aver bisogno di qualcosa del genere AMD (require.js)
Peeter

1
O potrei semplicemente voler fare un confronto molto semplice piuttosto che includere un'altra biblioteca nel mio progetto :)
AmericanUmlaut

Troppo tardi per modificarlo :(. Volevo aggiungere - request.js non è anche la soluzione giusta per la convalida dell'input (gli oggetti init che ho citato nel mio commento iniziale). Se hai un oggetto che ti aspetti di essere popolato con valori prima che lo script venga caricato, quindi è utile generare un'eccezione se non sono definiti.
AmericanUmlaut

1
No, perché typeof restituisce una stringa. Quindi typeof undefined restituisce "undefined". window.input! == undefined (se la tua variabile è nella posizione globale)
Peeter

5

Se sei davvero preoccupato per la ridefinizione di undefined, puoi proteggerti da questo con un metodo di supporto come questo:

function is_undefined(value) {
   var undefined_check; // instantiate a new variable which gets initialized to the real undefined value
   return value === undefined_check;
}

Questo funziona perché quando qualcuno scrive undefined = "foo"lascia solo il nome undefined riferimento a un nuovo valore, ma non cambia il valore effettivo di undefined.


1
Tuttavia, ora hai introdotto una chiamata di funzione, che danneggerà le prestazioni.
Tim Down,

Non penso che questa chiamata di funzione uccida le prestazioni, è molto più probabile che il DOM sia il collo di bottiglia. Ma comunque, se hai la tua solita grande funzione anonima che contiene la tua libreria, puoi anche definirla undefined_checkin alto e quindi usarla ovunque nel tuo codice.
Ivo Wetzel,

1
D'accordo, e non sto dicendo che questa è una cattiva idea. Vale la pena sottolineare che la chiamata a questa funzione funzionerà più lentamente rispetto al typeofcontrollo.
Tim Down,

Penso che questa funzione sia abbastanza semplice da essere integrata, quindi le prestazioni non ne risentirebbero.
huyz,

4
@TimDown: primo codice di scrittura, leggibile. secondo codice di scrittura, che è gestibile e, quindi, se è davvero a rallentare. quindi pensa alle prestazioni.
andreas,

4

È inoltre possibile utilizzare l'operatore void per ottenere un valore indefinito:

if (input !== void 0) {
    // do stuff    
}

(E sì, come notato in un'altra risposta, questo genererà un errore se la variabile non è stata dichiarata, ma questo caso può spesso essere escluso dall'ispezione del codice o dal refactoring del codice, ad esempio utilizzando window.input !== void 0per testare variabili globali o aggiungere var input.)


1

In realtà mi sono imbattuto (typeof input !== 'undefined')in questo scenario in cui viene utilizzato per fornire parametri di funzione predefiniti:

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

ES6 offre nuovi modi per introdurre i parametri delle funzioni predefinite in questo modo:

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

Questo è meno dettagliato e più pulito della prima opzione.


1

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  console.log(greeting,name);
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

//ES6 provides new ways of introducing default function parameters this way:

function greet2(name = 'Student', greeting = 'Welcome') {
//  return '${greeting} ${name}!';
console.log(greeting,name);
}

greet2(); // Welcome Student!
greet2('James'); // Welcome James!
greet2('Richard', 'Howdy'); // Howdy Richard!


0

(function(){

  var a= b = 3;
  var ed = 103;
  
})();



//console.log(ed); //ed is not defined

console.log("a defined? " + (typeof a !== 'undefined')); //no define
console.log("b defined? " + (typeof b !== 'undefined')); //yes define
console.log(typeof(b)); //number
console.log(typeof(4+7));   //number
console.log(b); //3
console.log(typeof("4"+"7")); //string
var e= "ggg";
console.log(typeof(e)); //string
 var ty=typeof(b);
console.log(ty); //number
console.log(typeof false); //boolean
console.log(typeof 1); //number
console.log(typeof 0); //number
console.log(typeof true); //boolean


console.log(typeof Math.tan);  //function
console.log(typeof function(){}); //function 

if(typeof neverDeclared == "undefined") //no errors
if(typeof neverDeclared === "undefined") //no errors

//if(neverDeclared == null) //showing error 


console.log(typeof {a:1}); //object
console.log(typeof null); //object
console.log(typeof JSON); //object
console.log(typeof Math); //object
console.log(typeof /a-z/); //object
console.log(typeof new Date()); //object

console.log(typeof afbc); //undefined
//console.log(typeof new);//error

document.write("<br> * oprator as math ");
var r=14*"4";
document.write(r);

document.write("<br> + oprator as string ");
var r=14+"44";
document.write(r);

document.write("<br> Minus Operator work as mathematic ");
var r=64-"44";
document.write(r);


document.write("<br>");
console.log(typeof(4*"7")); //returns number
console.log(typeof(4+"7")); //returns string




 
Interview Question in JavaScript


Potete fornire una spiegazione?
jhpratt GOFUNDME RELICENSING

Esistono sei valori possibili che typeof restituisce: object, boolean, function, number, string e undefined. L'operatore typeof viene utilizzato per ottenere il tipo di dati (restituisce una stringa) del suo operando. L'operando può essere una struttura letterale o di dati come una variabile, una funzione o un oggetto. L'operatore restituisce il tipo di dati. Sintassi typeof operando o typeof (operando)
Avinash Maurya,

0

var bar = null;
console.log(typeof bar === "object"); //true yes 
//because null a datatype of object

var barf = "dff";
console.log(typeof barf.constructor);//function


console.log(Array.isArray(bar));//falsss


console.log((bar !== null) && (bar.constructor === Object)); //false

console.log((bar !== null) && (typeof bar === "object"));  // logs false
//because bar!==null, bar is a object


console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); //false

console.log(typeof bar === typeof object); //false
console.log(typeof bar2 === typeof undefined); //true
console.log(typeof bar3 === typeof undefinedff); //true
console.log(typeof bar2 == typeof undefined); //true

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); //false


-7
if (input == undefined) { ... }

funziona benissimo. Ovviamente non è un nullconfronto, ma di solito trovo che se ho bisogno di distinguere tra undefinede null, in realtà ho piuttosto bisogno di distinguere tra undefinede solo qualsiasi valore falso, quindi

else if (input) { ... }

lo fa.

Se un programma lo ridefinisce undefined, è comunque davvero braindead.

L'unica ragione che mi viene in mente era per la compatibilità con IE4, non capiva la undefinedparola chiave (che non è in realtà una parola chiave, sfortunatamente), ma ovviamente i valori potevano essere undefined , quindi dovevi avere questo:

var undefined;

e il confronto sopra funzionerebbe perfettamente.

Nel tuo secondo esempio, probabilmente hai bisogno di doppie parentesi per rendere felice la lanugine?


Il tuo input == undefinedritorno truesu un nullinput.
mgol
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.