typeof! == "undefined" vs.! = null

491

Ich sehe oft JavaScript-Code, der auf folgende Weise nach undefinierten Parametern usw. sucht:

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

Dies scheint etwas verschwenderisch zu sein, da es sowohl eine Typensuche als auch einen Zeichenfolgenvergleich beinhaltet, ganz zu schweigen von seiner Ausführlichkeit. Es wird benötigt, weil undefinedes jedoch umbenannt werden könnte.

Meine Frage ist:
Wie ist dieser Code besser als dieser Ansatz:

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

Soweit ich weiß, können Sie nicht neu definieren null, damit es nicht unerwartet kaputt geht. Und aufgrund des Typzwangs des !=Operators wird sowohl nach undefinedals auch nach null... gesucht, was häufig genau das ist, was Sie möchten (z. B. für optionale Funktionsparameter).

Diese Form scheint jedoch nicht weit verbreitet zu sein, und JSLint schreit Sie sogar an, weil Sie den bösen !=Operator verwendet haben.

Warum wird das als schlechter Stil angesehen?

Derek Thurn
quelle
13
@ Marcel, es gibt keinen wirklichen Unterschied, aber es gibt zwei Gründe dafür. Zum einen ist es für manche klarer zu lesen. Und der zweite Grund ist, dass es ein versehentliches Überschreiben einer Variablen verhindert. Haben Sie dies jemals getan: if (foo = "value"), wenn Sie einen Vergleich durchführen möchten. Wenn Sie es sich zur Gewohnheit machen, die Variable im Zuweisungs- / Vergleichsoperator umzukehren, haben Sie dieses Problem nicht.
Layke
29
Für einige (einschließlich mich) ist dies tatsächlich schwieriger zu lesen. Außerdem warnen die meisten IDEs Sie vor versehentlicher Zuweisung. Aber ich benutze dieses Formular immer noch, wenn die verglichene Variable sehr lang ist. YMMV.
Johndodo
15
@MarcelKorpel Dies wird "Yoda Bedingung" genannt: umumble.com/blogs/Programming/321
kol
55
Es ist schwieriger zu lesen. Man sagt nicht "Nicht leer ist die Flasche".
Noel Abrahams
11
if (null != input)ist nur "Yoda Speak" für den englischen Sprecher (von einem bin ich ... uuammmmm). Wenn sie also dem gleichen entsprechen, ist es wirklich nur Semantik. MEINER BESCHEIDENEN MEINUNG NACH.
webLacky3rdClass

Antworten:

710

typeof ist sicherer, da der Bezeichner noch nie deklariert wurde:

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

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined
Seanmonstar
quelle
3
if ((typeof neverDeclared! == "undefined") && (neverDeclared! == null)) {return true; } else {return false; }
Anthony DiSanti
88
Verwenden Sie === beim Vergleich mit null / undefiniert.
MyGGaN
47
@MyGGaN nur, wenn Sie zwischen den beiden unterscheiden möchten. In vielen Fällen ==kann es besser sein, da es sowohl auf null als auch auf undefiniert testet.
Seanmonstar
10
Ich kann keinen Unterschied zwischen typeof somevar == 'undefined' und typeof somevar === 'undefined' feststellen, da typeof immer einen String zurückgibt. Für null wird 'object' zurückgegeben. Oder könnte es sein, dass ich falsch liege?
TomTom
2
Ich glaube, dass der Kommentar von @ TomTom der Kern des Problems ist - ich kann nicht verstehen, warum man die Operatoren !==oder verwendet ===, wenn man einen Wert vergleicht, dessen Typ als Zeichenfolge bekannt ist.
Nicolas Rinaudo
49

Wenn die Variable deklariert ist (entweder mit dem varSchlüsselwort, als Funktionsargument oder als globale Variable), ist der beste Weg, dies zu tun, meiner Meinung nach:

if (my_variable === undefined)

jQuery macht es, also ist es gut genug für mich :-)

Andernfalls müssen Sie verwenden typeof, um a zu vermeiden ReferenceError.

Wenn Sie erwarten, dass undefiniert neu definiert wird, können Sie Ihren Code wie folgt umbrechen:

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

Oder erhalten Sie es über den voidBetreiber:

const undefined = void 0;
// also safe
Joey Adams
quelle
1
Wenn undefined bereits definiert wurde, würden Sie es dann nicht über einen Parameter mit dem Namen undefined an Ihre anonyme Funktion übergeben und nichts erreichen?
Anthony DiSanti
20
@Anthony DiSanti: Nein, undefinedist der Name des Funktionsparameters, nicht sein Wert. Es wird nichts an die Funktion übergeben, was bedeutet, dass der Wert des ersten Parameters undefiniert ist.
Joey Adams
3
Ah mein Fehler, danke für das Follow-up. Ich habe meine Stimme entfernt, tut mir leid.
Anthony DiSanti
2
Warum eine Ausnahme schreiben, um die undefinierte Deklaration durch einen anderen Entwickler zu behandeln, wenn Sie dies zunächst richtig machen können? jQuery umschließt die anfängliche anonyme Funktion, wie Sie sie in Ihrer Funktion anzeigen, um sicherzustellen, dass undefiniert nicht definiert wurde, und um die minimierte Größe zu verringern. Einfach ausgedrückt, wenn es auf diese Weise zu unerwarteten Ergebnissen führen kann, warum sollte es riskant sein, dass die Programmierung verzögert wird, um ein Eingeben zu vermeiden (typeof variable === 'undefined'). Was wäre, wenn wir wollten (Typ der Variablen === 'Objekt'), sollten wir eine Standardvariable bereitstellen, die ebenfalls ein Objekt ist, damit wir dies tun können (Variable === Objekt)?
Fyrye
28

gute Möglichkeit:

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

Am besten sehen Sie jedoch nach:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings
Scherz
quelle
6
var undefined = function () {}; if (typeof neverDeclared === typeof undefined); NeverDecalred! = 'Funktion'; jsfiddle.net/hbPZ5 return typeof var; gibt eine Zeichenfolge zurück. Keine Fehler oder Zeichenfolgen, aber nicht immer erwartete Ergebnisse. Zugegeben, Entwickler sollten nicht undefiniert deklarieren, aber es gibt einige Frameworks und Bibliotheken, die dies tun.
Fyrye
1
Ich benutze hauptsächlich, if (typeof neverDeclared === typeof undefined) { aber Lint wirft einen Fehler. "Ich habe eine Zeichenfolge erwartet und stattdessen 'typeof' gesehen." Wie würden Sie diesen Fehler umgehen? Sollten wir uns den Forderungen von Lint unterwerfen und stattdessen den "guten Weg" verwenden?
Ayelis
2
@fyrye Kennen Sie JavaScript-Bibliotheken / Frameworks, die tatsächlich undefiniert mutieren? Ich weiß, dass es möglich ist; aber ich würde gerne ein wildes Beispiel finden: "Hier könnten Sie diesem bösen Gnu begegnen!"
Bigtunacan
4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich
1
Es ist fehleranfällig, da Sie sich nur darauf verlassen, dass eine bestimmte Variable ("undefiniert") nicht definiert wird. Was falsch sein kann, wie andere Beiträge gezeigt haben. Sie können immer tun, if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {aber es ist ziemlich lang.
Pierre-Olivier Vares
12

Sie sollten sich nicht wirklich Sorgen machen, dass undefiniert umbenannt wird. Wenn jemand undefiniert umbenennt, haben Sie viel mehr Probleme als nur ein paar, wenn die Prüfung fehlschlägt. Wenn Sie Ihren Code wirklich schützen möchten, verpacken Sie ihn wie folgt in ein IFFE (sofort aufgerufener Funktionsausdruck):

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

Wenn Sie mit globalen Variablen (die bereits falsch sind) in einer Browserumgebung arbeiten, würde ich nach Undefiniertem wie folgt suchen:

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

Da globale Variablen Teil des Fensterobjekts sind, können Sie einfach gegen undefiniert prüfen, anstatt sie in eine Zeichenfolge umzuwandeln und Zeichenfolgen zu vergleichen.

Warum sind Ihre Variablen nicht definiert? Ich habe viel Code gesehen, in dem sie die Existenz einer Variablen überprüfen und darauf basierend eine Aktion ausführen. Ich habe nicht ein einziges Mal gesehen, wo dieser Ansatz richtig war.

Peeter
quelle
1
Eingabevalidierung und Abhängigkeitsprüfung sind gute Gründe, dies zu verwenden. Wenn ich Javascript-Dateien habe, die von anderen Dateien abhängig sind, die geladen wurden, oder von Objekten, die deklariert wurden, deklariert wurde, ist es nützlich, Objekte oder Eigenschaften, von denen eine Datei abhängig ist, gegen undefiniert zu testen und eine nette Ausnahme auszulösen, anstatt Ihr Skript an einem unvorhersehbaren Ort fehlschlagen zu lassen.
AmericanUmlaut
Es hört sich so an, als ob Sie etwas in den Zeilen von AMD benötigen (require.js)
Peeter
1
Oder ich möchte einfach nur einen sehr einfachen Vergleich anstellen, anstatt eine andere Bibliothek in mein Projekt aufzunehmen :)
AmericanUmlaut
Zu spät zum Bearbeiten :(. Wollte hinzufügen - require.js ist auch nicht die richtige Lösung für die Eingabevalidierung (die Init-Objekte, die ich in meinem ersten Kommentar erwähnt habe). Wenn Sie ein Objekt haben, von dem Sie erwarten, dass es mit bestimmten Daten gefüllt ist Werte, bevor das Skript geladen wird, dann ist es nützlich, eine Ausnahme auszulösen, wenn sie nicht definiert sind.
AmericanUmlaut
1
Nein, da typeof eine Zeichenfolge zurückgibt. Typeof undefined gibt also "undefined" zurück. window.input! == undefined (wenn sich Ihre Variable im globalen Bereich befindet)
Peeter
5

Wenn Sie sich wirklich Sorgen darüber machen, dass undefiniert neu definiert wird, können Sie sich mit einer Hilfsmethode wie dieser davor schützen:

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

Dies funktioniert, weil jemand beim Schreiben undefined = "foo"nur den Namen undefined auf einen neuen Wert verweisen lässt , aber den tatsächlichen Wert von nicht ändert undefined.

Ivo Wetzel
quelle
1
Sie haben jetzt jedoch einen Funktionsaufruf eingeführt, der die Leistung beeinträchtigt.
Tim Down
Ich glaube nicht, dass dieser Funktionsaufruf die Leistung beeinträchtigt. Es ist viel wahrscheinlicher, dass das DOM der Engpass ist. Wenn Sie jedoch Ihre übliche große anonyme Funktion haben, die Ihre Bibliothek enthält, können Sie diese auch oben definieren undefined_checkund dann überall in Ihrem Code verwenden.
Ivo Wetzel
1
Einverstanden, und ich sage nicht, dass dies eine schlechte Idee ist. Es ist nur erwähnenswert, dass das Aufrufen dieser Funktion langsamer ausgeführt wird als das Durchführen einer typeofÜberprüfung.
Tim Down
Ich denke, diese Funktion ist so einfach, dass sie inline ist, sodass die Leistung nicht beeinträchtigt wird.
Huyz
4
@ TimDown: Zuerst Code schreiben, der lesbar ist. zweiter Code schreiben, das ist wartbar, und dann, wenn es wirklich zu langsam ist. dann denken Sie an die Leistung.
Andreas
4

Sie können auch den void-Operator verwenden, um einen undefinierten Wert zu erhalten:

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

(Und ja, wie in einer anderen Antwort angegeben, wird dies einen Fehler auslösen, wenn die Variable nicht deklariert wurde. Dieser Fall kann jedoch häufig entweder durch Code-Inspektion oder durch Code-Refactoring ausgeschlossen werden, z. B. window.input !== void 0zum Testen globaler Variablen oder zum Hinzufügen var input.)

Claude
quelle
1

Ich bin tatsächlich auf etwas gestoßen, wenn es (typeof input !== 'undefined')in diesem Szenario verwendet wird, um Standardfunktionsparameter bereitzustellen:

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 bietet neue Möglichkeiten zur Einführung von Standardfunktionsparametern auf folgende Weise:

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

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

Dies ist weniger ausführlich und sauberer als die erste Option.

JSpecs
quelle
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!

Avinash Maurya
quelle
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

Avinash Maurya
quelle
Können Sie eine Erklärung geben?
Jhpratt GOFUNDME RELICENSING
Es gibt sechs mögliche Werte, die typeof zurückgibt: object, boolean, function, number, string und undefined. Der Operator typeof wird verwendet, um den Datentyp (gibt eine Zeichenfolge zurück) seines Operanden abzurufen. Der Operand kann entweder ein Literal oder eine Datenstruktur wie eine Variable, eine Funktion oder ein Objekt sein. Der Operator gibt den Datentyp zurück. Syntax Typ des Operanden oder Typ des (Operanden)
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

Avinash Maurya
quelle
-7
if (input == undefined) { ... }

funktioniert gut. Es ist natürlich kein nullVergleich, aber ich finde normalerweise, dass ich, wenn ich zwischen undefinedund unterscheiden muss null, eigentlich eher zwischen undefinedund nur irgendeinen falschen Wert unterscheiden muss, also

else if (input) { ... }

macht es.

Wenn ein Programm neu definiert undefined, ist es sowieso wirklich geisteskrank.

Der einzige Grund, an den ich denken kann, war die IE4-Kompatibilität. Es hat das undefinedSchlüsselwort nicht verstanden (was leider eigentlich kein Schlüsselwort ist), aber natürlich könnten Werte sein undefined , also musste man folgendes haben:

var undefined;

und der obige Vergleich würde gut funktionieren.

In Ihrem zweiten Beispiel benötigen Sie wahrscheinlich doppelte Klammern, um Flusen glücklich zu machen?

UniquePhoton
quelle
Sie input == undefinedwerden truebei einer nullEingabe zurückkehren.
mgol