7 Tipps zum Umgang mit undefinierten in JavaScript

Die meisten modernen Sprachen wie Ruby, Python oder Java haben einen einzelnen Nullwert (nil oder null), was ein vernünftiger Ansatz erscheint.

Aber JavaScript ist anders.

null, aber auch undefined stellen in JavaScript leere Werte dar. Was ist der genaue Unterschied zwischen ihnen?

Die kurze Antwort lautet, dass der JavaScript-Interpreter beim Zugriff auf eine noch nicht initialisierte Variablen- oder Objekteigenschaft undefined zurückgibt. Beispiel:

Auf der anderen Seite repräsentiert null ein fehlendes Objekt Referenz. JavaScript initialisiert keine Variablen oder Objekteigenschaften mit null.

Einige native Methoden wie String.prototype.match() können null zurückgeben, um ein fehlendes Objekt zu kennzeichnen. Schauen Sie sich das Beispiel an:

Da JavaScript zulässig ist, haben Entwickler die Versuchung, auf nicht initialisierte Werte zuzugreifen. Ich bin auch solch einer schlechten Praxis schuldig.

Oft verursachen solche riskanten Aktionen undefined verwandte Fehler:

  • TypeError: "undefined" is not a function
  • TypeError: Cannot read property "<prop-name>" of undefined
  • und ähnliche Tippfehler.

JavaScript-Entwickler können die Ironie dieses Witzes verstehen :

Um solche Fehler zu reduzieren, müssen Sie die Fälle verstehen, in denen undefined wird generiert. Lassen Sie uns undefined und seine Auswirkungen auf die Codesicherheit untersuchen.

1. Was ist undefiniert

JavaScript hat 6 primitive Typen:

Und einen getrennten Objekttyp: {name: "Dmitri"} , .

Aus 6 primitiven Typen undefined ist ein spezieller Wert mit einem eigenen Typ Undefined. Gemäß ECMAScript-Spezifikation:

Der undefinierte Wert primitiver Wert wird verwendet, wenn einer Variablen kein Wert zugewiesen wurde.

Der Standard definiert klar, dass Sie undefined erhalten, wenn Sie auf nicht initialisierte Variablen, nicht vorhandene Objekteigenschaften zugreifen. nicht vorhandene Array-Elemente und dergleichen.

Einige Beispiele:

Das obige Beispiel zeigt, dass auf Folgendes zugegriffen wird:

  • eine nicht initialisierte Variable number
  • eine nicht vorhandene Objekteigenschaft movie.year
  • oder ein nicht vorhandenes Array-Element movies

werden mit undefined ausgewertet.

Die ECMAScript-Spezifikation definiert den Typ des undefined -Werts:

Undefinierter Typ ist Ein Typ, dessen einziger Wert der Wert undefined ist.

In diesem Sinne gibt die "undefined" Zeichenfolge für einen undefined -Wert zurück:

Natürlich funktioniert typeof gut, um zu überprüfen, ob eine Variable einen undefined -Wert enthält:

2. Szenarien, die eine undefinierte

2.1 Uninitialisierte Variable

Eine deklarierte Variable, der jedoch noch kein Wert zugewiesen wurde (nicht initialisiert), ist standardmäßig undefined.

Schlicht und einfach:

myVariable ist deklariert und noch nicht mit einem Wert versehen. Der Zugriff auf die Variable ergibt undefined.

Ein effizienter Ansatz zur Lösung der Probleme nicht initialisierter Variablen besteht darin, nach Möglichkeit einen Anfangswert zuzuweisen. Je weniger die Variable in einem nicht initialisierten Zustand existiert, desto besser.

Idealerweise würden Sie sofort nach der Deklaration const myVariable = "Initial value" einen Wert zuweisen. Das ist aber nicht immer möglich.

Tipp 1: Bevorzugen Sie const, verwenden Sie andernfalls let, verabschieden Sie sich jedoch von

Meiner Meinung nach ist eine der besten Funktionen von ECMAScript 2015 die neue Methode zum Deklarieren von Variablen mit const und let. Es ist ein großer Schritt nach vorne.

const und let haben einen Blockbereich (im Gegensatz zu einem älteren Funktionsbereich var) und existieren in einer zeitlichen Totzone bis zur Deklarationslinie.

Ich empfehle die Variable const, wenn sich ihr Wert nicht ändert. Es entsteht eine unveränderliche Bindung.

Eine der netten Funktionen von const ist, dass Sie der Variablen const myVariable = "initial" einen Anfangswert zuweisen müssen. Die Variable ist nicht dem nicht initialisierten Status ausgesetzt und der Zugriff auf undefined ist nicht möglich.

Überprüfen wir die Funktion, mit der überprüft wird, ob ein Wort ein Palindrom ist:

length und half Variablen werden einmal mit einem Wert versehen. Es erscheint sinnvoll, sie als const zu deklarieren, da sich diese Variablen nicht ändern werden.

Verwenden Sie die let -Deklaration für Variablen, deren Wert sich ändern kann. Weisen Sie nach Möglichkeit sofort einen Anfangswert zu, z. let index = 0.

Was ist mit der alten Schule var? Mein Vorschlag ist, es nicht mehr zu benutzen.

var Deklarationsproblem ist das Heben von Variablen innerhalb des Funktionsbereichs. Sie können eine var -Variable irgendwo am Ende des Funktionsumfangs deklarieren, können jedoch vor der Deklaration darauf zugreifen: und Sie erhalten eine undefined.

myVariable ist zugänglich und enthält undefined noch vor der Deklarationszeile: var myVariable = "Initial value".

Im Gegensatz dazu kann auf eine const oder let -Variable nicht vor der Deklarationszeile zugegriffen werden – der Variablen befindet sich vor der Deklaration in einer zeitlichen Totzone. Und das ist schön, weil Sie weniger Chancen haben, auf eine undefined zuzugreifen.

Das obige Beispiel wurde stattdessen mit let aktualisiert von var) löst ein ReferenceError aus, da auf die Variable in der zeitlichen Totzone nicht zugegriffen werden kann.

Durch die Förderung der Verwendung von const für unveränderliche Bindungen oder let wird ansonsten eine Vorgehensweise sichergestellt, die das Erscheinungsbild von Uninitialisierten verringert Variable.

Tipp 2: Kohäsion erhöhen

Kohäsion kennzeichnet den Grad, in dem die Elemente eines Moduls (Namespace, Klasse, Methode, Codeblock) zusammengehören. Der Zusammenhalt kann hoch oder niedrig sein.

Ein Modul mit hoher Kohäsion ist vorzuziehen, da sich die Elemente eines solchen Moduls ausschließlich auf eine einzelne Aufgabe konzentrieren. Es macht das Modul:

  • Fokussiert und verständlich: leichter zu verstehen, was das Modul tut
  • Wartbar und einfacher umzugestalten: Die Änderung im Modul betrifft weniger Module
  • Wiederverwendbar: Da das Modul auf eine einzelne Aufgabe konzentriert ist, kann es leichter wiederverwendet werden.
  • Testbar: Sie können ein Modul, das sich auf eine einzelne Aufgabe konzentriert, einfacher testen.

Hohe Kohäsion bei lockerer Kopplung ist das Merkmal eines gut konzipierten Systems.

Ein Codeblock kann als kleines Modul betrachtet werden. Um von den Vorteilen einer hohen Kohäsion zu profitieren, halten Sie die Variablen so nah wie möglich an dem Codeblock, der sie verwendet.

Wenn beispielsweise eine Variable nur existiert, um die Logik des Blockumfangs zu bilden, deklarieren Sie die Variable und machen Sie sie nur innerhalb dieses Blocks lebendig (mit const oder let Deklarationen). Setzen Sie diese Variable nicht dem Bereich des äußeren Blocks aus, da sich der äußere Block nicht um diese Variable kümmern sollte.

Ein klassisches Beispiel für die unnötig verlängerte Lebensdauer von Variablen ist die Verwendung von for Zyklus innerhalb einer Funktion:

index, item und length Variablen werden am Anfang des Funktionskörpers deklariert. Sie werden jedoch erst gegen Ende verwendet. Was ist das Problem bei diesem Ansatz?

Zwischen der Deklaration oben und der Verwendung in der Anweisung for werden die Variablen index, item sind nicht initialisiert und undefined ausgesetzt. Sie haben einen unangemessen langen Lebenszyklus im gesamten Funktionsumfang.

Ein besserer Ansatz besteht darin, diese Variablen so nah wie möglich an ihren Verwendungsort zu verschieben:

index und item Variablen existieren nur im Blockbereich der Anweisung for. Sie haben außerhalb von for keine Bedeutung.
Die Variable length wird auch in der Nähe der Verwendungsquelle deklariert.

Warum ist die geänderte Version besser als die ursprüngliche? Mal sehen:

  • Die Variablen sind keinem nicht initialisierten Status ausgesetzt, sodass Sie kein Risiko haben, auf undefined
  • zuzugreifen Variablen, die so nah wie möglich an ihrem Verwendungsort liegen, erhöhen die Lesbarkeit des Codes.
  • Hoch zusammenhängende Codestücke lassen sich leichter umgestalten und bei Bedarf in separate Funktionen extrahieren.

2.2 Zugriff Eine nicht vorhandene Eigenschaft

Beim Zugriff auf eine nicht vorhandene Objekteigenschaft gibt JavaScript undefined zurück.

Lassen Sie uns dies in einem Beispiel demonstrieren:

favoriteMovie ist ein Objekt mit einer einzelnen Eigenschaft title. Der Zugriff auf eine nicht vorhandene Eigenschaft actors mithilfe eines Eigenschaftenzugriffs favoriteMovie.actors ergibt undefined.

Der Zugriff auf eine nicht vorhandene Eigenschaft löst keinen Fehler aus. Das Problem tritt auf, wenn versucht wird, Daten von der nicht vorhandenen Eigenschaft abzurufen. Dies ist die häufigste undefined -Falle, die sich in der bekannten Fehlermeldung TypeError: Cannot read property <prop> of undefined.

Lassen Sie uns das vorherige Code-Snippet leicht modifizieren, um einen TypeError -Wurf zu veranschaulichen:

favoriteMovie hat nicht die Eigenschaft actors, also favoriteMovie.actors ergibt undefined.

Wenn Sie mit dem Ausdruck favoriteMovie.actors auf das erste Element eines undefined -Werts zugreifen, wird eine TypeError.

Die zulässige Natur von JavaScript, die den Zugriff auf nicht vorhandene Eigenschaften ermöglicht, ist eine Quelle des Nichtdeterminismus: Die Eigenschaft kann festgelegt werden oder nicht. Der gute Weg, um dieses Problem zu umgehen, besteht darin, das Objekt so einzuschränken, dass es immer die Eigenschaften definiert hat, die es enthält.

Leider haben Sie häufig keine Kontrolle über die Objekte. Solche Objekte können in verschiedenen Szenarien unterschiedliche Eigenschaften haben. Sie müssen also alle diese Szenarien manuell behandeln.

Implementieren wir eine Funktion append(array, toAppend), die am Anfang und / oder am Ende eines Arrays neuer Elemente hinzugefügt wird. Der Parameter toAppend akzeptiert ein Objekt mit den folgenden Eigenschaften:

  • first: Element, das am Anfang von array
  • last: Element, das am Ende von array eingefügt wird.

Die Funktion gibt eine neue Array-Instanz zurück, ohne das ursprüngliche Array zu ändern.

Die erste Version von append(), ein bisschen naiv, könnte folgendermaßen aussehen:

Weil toAppend kann die Eigenschaften first oder last weglassen. Es muss überprüft werden, ob diese Eigenschaften in .

Ein Eigenschafts-Accessor wertet undefined aus, wenn die Eigenschaft nicht vorhanden ist. Die erste Versuchung zu prüfen, ob first oder last Eigenschaften vorhanden sind, besteht darin, sie anhand von undefined. Dies wird unter den Bedingungen if(toAppend.first){} und if(toAppend.last){}

durchgeführt. Nicht so schnell. Dieser Ansatz hat einen Nachteil. undefined sowie false, null, 0, NaN und "" sind falsche Werte.

In der aktuellen Implementierung von append() können mit der Funktion keine falschen Elemente eingefügt werden:

In den folgenden Tipps wird erläutert, wie Sie die Existenz der Eigenschaft korrekt überprüfen.

Tipp 3: Überprüfen Sie die Existenz der Eigenschaft

Glücklicherweise bietet JavaScript Eine Reihe von Möglichkeiten, um festzustellen, ob das Objekt eine bestimmte Eigenschaft hat:

  • obj.prop !== undefined: Vergleichen Sie mit undefined direkt
  • typeof obj.prop !== "undefined": Überprüfen Sie den Eigenschaftswerttyp.
  • obj.hasOwnProperty("prop"): Überprüfen Sie, ob die Objekt hat eine eigene Eigenschaft
  • "prop" in obj: Überprüfen Sie, ob das Objekt eine eigene oder geerbte Eigenschaft hat.

Meine Empfehlung lautet: Verwenden Sie den Operator in. Es hat eine kurze und süße Syntax. in schlägt eine klare Absicht vor, zu überprüfen, ob ein Objekt eine bestimmte Eigenschaft hat, ohne auf den tatsächlichen Eigenschaftswert zuzugreifen.

obj.hasOwnProperty("prop") ist ebenfalls eine gute Lösung. Es ist etwas länger als der Operator in und wird nur in den Eigenschaften des Objekts überprüft.

Verbessern wir die Funktion append(array, toAppend) mit dem Operator in:

"first" in toAppend (und "last" in toAppend) ist true, ob die entsprechende Eigenschaft vorhanden ist, false sonst.

in Der Operator behebt das Problem beim Einfügen falscher Elemente. 0 und false. Wenn Sie nun diese Elemente am Anfang und am Ende von hinzufügen, erhalten Sie das erwartete Ergebnis .

Tipp 4: Destrukturierung für den Zugriff auf Objekteigenschaften

Beim Zugriff auf eine Objekteigenschaft muss manchmal ein Standardwert festgelegt werden, wenn die Eigenschaft nicht vorhanden ist.

Sie können in zusammen mit einem ternären Operator verwenden, um dies zu erreichen:

Die Syntax des ternären Operators wird entmutigend, wenn die Anzahl der zu überprüfenden Eigenschaften zunimmt. Für jede Eigenschaft müssen Sie eine neue Codezeile erstellen, um die Standardeinstellungen zu verarbeiten. Dadurch wird eine hässliche Wand aus ähnlich aussehenden ternären Operatoren vergrößert.

Um einen eleganteren Ansatz zu verwenden, sollten Sie sich mit einer großartigen ES2015-Funktion vertraut machen, die als Objektzerstörung bezeichnet wird.

Die Objektdestrukturierung ermöglicht die Inline-Extraktion von Objekteigenschaftswerten direkt in Variablen und das Festlegen eines Standardwerts, wenn die Eigenschaft nicht vorhanden ist. Eine praktische Syntax, um zu vermeiden, dass direkt mit undefined umgegangen wird.

In der Tat ist die Eigenschaftsextraktion jetzt präzise:

Um die Dinge in Aktion zu sehen, definieren wir eine nützliche Funktion, die eine Zeichenfolge in Anführungszeichen setzt.

quote(subject, config) akzeptiert das erste Argument als zu umschließenden String. Das zweite Argument config ist ein Objekt mit den Eigenschaften:

Um die Vorteile der Objektzerstörung anzuwenden, implementieren wir quote():

const { char = """, skipIfQuoted = true } = config Die Destrukturierungszuweisung in einer Zeile extrahiert die Eigenschaften char und skipIfQuoted vom Objekt config.
Wenn im Objekt config einige Eigenschaften fehlen, legt die Destrukturierungszuweisung die Standardwerte fest : """ für char und false für skipIfQuoted.

Glücklicherweise gibt es in der Funktion noch Verbesserungspotenzial.

Verschieben wir die Destrukturierungszuweisung in den Parameterbereich. Legen Sie für den Parameter config einen Standardwert fest (ein leeres Objekt { }), um das zweite Argument zu überspringen, wenn die Standardeinstellungen ausreichen.

Die Destrukturierungszuweisung ersetzt den Parameter config in der Signatur der Funktion. Das gefällt mir: quote() wird eine Zeile kürzer.

= {} auf der rechten Seite der Destrukturierungszuweisung stellt sicher, dass ein leeres Objekt verwendet wird, wenn das zweite Argument überhaupt nicht angegeben wird quote("Sunny day").

Die Objektzerstörung ist eine leistungsstarke Funktion, mit der das Extrahieren von Eigenschaften aus Objekten effizient durchgeführt werden kann. Ich mag die Möglichkeit, einen Standardwert anzugeben, der zurückgegeben werden soll, wenn die Eigenschaft, auf die zugegriffen wird, nicht vorhanden ist. Infolgedessen vermeiden Sie undefined und den damit verbundenen Aufwand.

Tipp 5: Füllen Sie das Objekt mit Standardeigenschaften.

Wenn nicht wie bei der Destrukturierungszuweisung für jede Eigenschaft Variablen erstellt werden müssen, kann das Objekt, dem einige Eigenschaften fehlen, gefüllt werden mit Standardwerten.

Der ES2015 Object.assign(target, source1, source2, ...) kopiert die Werte aller aufzählbaren eigenen Eigenschaften von einem oder mehreren Quellobjekten in das Zielobjekt. Die Funktion gibt das Zielobjekt zurück.

Beispielsweise müssen Sie auf die Eigenschaften des unsafeOptions -Objekts zugreifen, das nicht immer alle Eigenschaften enthält.

Um undefined beim Zugriff auf eine nicht vorhandene Eigenschaft über unsafeOptions zu vermeiden, nehmen wir einige Anpassungen vor:

  • Definieren Sie ein Objekt defaults, das die Standardeigenschaftswerte enthält.
  • Rufen Sie zum Erstellen Object.assign({ }, defaults, unsafeOptions) auf ein neues Objekt options. Das neue Objekt empfängt alle Eigenschaften von unsafeOptions, die fehlenden werden jedoch von defaults übernommen.

unsafeOptions enthält nur die Eigenschaft fontSize. Das Objekt defaults definiert die Standardwerte für die Eigenschaften fontSize und color.

Object.assign() verwendet das erste Argument als Zielobjekt {}. Das Zielobjekt empfängt den Wert der Eigenschaft fontSize vom Quellobjekt unsafeOptions. Und der Wert der Eigenschaft color aus dem Quellobjekt defaults, da unsafeOptions nichts enthält color.

Die Reihenfolge, in der die Quellobjekte aufgelistet werden, spielt eine Rolle: Spätere Eigenschaften von Quellobjekten überschreiben frühere.

Sie können jetzt sicher auf alle Eigenschaften des Objekts options zugreifen, einschließlich options.color, die in unsafeOptions anfangs.

Glücklicherweise gibt es eine einfachere Alternative, um das Objekt mit Standardeigenschaften zu füllen.Ich empfehle, die Spread-Eigenschaften in Objektinitialisierern zu verwenden.

Verwenden Sie anstelle des Aufrufs Object.assign() die Objektverbreitungssyntax, um alle eigenen und aufzählbaren Eigenschaften von Quellobjekten in das Zielobjekt zu kopieren:

Die Der Objektinitialisierer verteilt Eigenschaften von defaults und unsafeOptions Quellobjekten. Die Reihenfolge, in der die Quellobjekte angegeben werden, ist wichtig: Spätere Eigenschaften von Quellobjekten überschreiben frühere.

Das Füllen eines unvollständigen Objekts mit Standardeigenschaftswerten ist eine effiziente Strategie, um Ihren Code sicher und dauerhaft zu machen. Unabhängig von der Situation enthält das Objekt immer den vollständigen Satz von Eigenschaften: undefined kann nicht generiert werden.

Bonus-Tipp: nullish coalescing

Der Operator nullish coalescing wird zu einem Standardwert ausgewertet, wenn sein Operand undefined oder :

Der Nullish Coalescing-Operator ist praktisch, um auf eine Objekteigenschaft zuzugreifen, während er einen Standardwert hat Diese Eigenschaft lautet undefined oder null:

styles Objekt hat nicht die Eigenschaft color, also styles.color Der Eigenschaftszugriff ist undefined. styles.color ?? "black" ergibt den Standardwert "black".

styles.fontSize ist 18, sodass der Null-Koaleszenzoperator den Eigenschaftswert .

2.3 Funktionsparameter

Die Funktionsparameter sind implizit standardmäßig undefined.

Normalerweise sollte eine mit einer bestimmten Anzahl von Parametern definierte Funktion mit derselben Anzahl von Argumenten aufgerufen werden. Dann erhalten die Parameter die erwarteten Werte:

Wenn multiply(5, 3), Die Parameter a und b erhalten 5 bzw. 3 Werte. Die Multiplikation wird wie erwartet berechnet: 5 * 3 = 15.

Was passiert, wenn Sie beim Aufruf ein Argument weglassen? Der entsprechende Parameter innerhalb der Funktion wird zu undefined.

Ändern Sie das vorherige Beispiel geringfügig, indem Sie die Funktion mit nur einem Argument aufrufen:

Der Aufruf multiply(5) wird mit einem einzigen Argument ausgeführt: Als Ergebnis ist der Parameter a 5, aber der Der Parameter b ist undefined.

Tipp 6: Standardparameterwert verwenden

Manchmal erfordert eine Funktion beim Aufruf nicht den vollständigen Satz von Argumenten. Sie können Standardeinstellungen für Parameter festlegen, die keinen Wert haben.

Erinnern wir uns an das vorherige Beispiel und verbessern wir es. Wenn der Parameter b undefined ist, verwenden Sie standardmäßig 2:

Die Funktion wird mit einem einzigen Argument multiply(5) aufgerufen. Zu Beginn ist der Parameter a 2 und b undefined.
Die bedingte Anweisung überprüft, ob b undefined ist. In diesem Fall legt die Zuweisung b = 2 einen Standardwert fest.

Obwohl die bereitgestellte Methode zum Zuweisen von Standardwerten funktioniert, empfehle ich nicht, direkt mit undefined zu vergleichen. Es ist ausführlich und sieht aus wie ein Hack.

Ein besserer Ansatz ist die Verwendung der Standardparameterfunktion ES2015. Es ist kurz, ausdrucksstark und keine direkten Vergleiche mit undefined.

Das Hinzufügen eines Standardwerts zum Parameter b = 2 sieht besser aus:

b = 2 in der Funktionssignatur stellt sicher, dass wenn b undefined ist, Der Parameter ist standardmäßig 2.

Die Standardparameterfunktion von ES2015 ist intuitiv und ausdrucksstark. Verwenden Sie diese Option immer, um Standardwerte für optionale Parameter festzulegen.

2.4 Funktionsrückgabewert

Implizit ohne return -Anweisung eine JavaScript-Funktion gibt undefined zurück.

Eine Funktion ohne return gibt implizit undefined zurück:

square() -Funktion gibt keine Berechnungsergebnisse zurück. Das Ergebnis des Funktionsaufrufs lautet undefined.

Die gleiche Situation tritt auf, wenn die Anweisung return vorhanden ist, jedoch ohne einen Ausdruck in der Nähe:

return; wird ausgeführt, gibt jedoch keinen Ausdruck zurück. Das Aufrufergebnis ist auch undefined.

Wenn Sie in der Nähe von return angeben, funktioniert der zurückzugebende Ausdruck wie erwartet:

Jetzt wird der Funktionsaufruf mit 4 ausgewertet, was 2 im Quadrat ist.

Tipp 7: Vertrauen Sie dem automatischen Einfügen von Semikolons nicht.

Die folgende Liste von Anweisungen in JavaScript muss mit Semikolons enden (;). :

  • leere Anweisung
  • let, const, var, import, export Deklarationen
  • Ausdrucksanweisung
  • debugger Anweisung
  • continue Anweisung, break Anweisung
  • throw Anweisung
  • return Anweisung

If Wenn Sie eine der obigen Anweisungen verwenden, müssen Sie am Ende ein Semikolon angeben:

Am Ende beider let Deklaration und return Anweisung wird ein obligatorisches Semikolon geschrieben.

Was passiert, wenn Sie diese nicht angeben möchten? Semikolons? In einer solchen Situation bietet ECMAScript einen ASI-Mechanismus (Automatic Semicolon Insertion), der die fehlenden Semikolons für Sie einfügt.

Mithilfe von ASI können Sie die Semikolons aus dem vorherigen Beispiel entfernen:

Der obige Text ist ein gültiger JavaScript-Code. Die fehlenden Semikolons werden automatisch für Sie eingefügt.

Auf den ersten Blick sieht es ziemlich vielversprechend aus. Mit dem ASI-Mechanismus können Sie unnötige Semikolons überspringen. Sie können den JavaScript-Code verkleinern und leichter lesen.

Es gibt eine kleine, aber nervige Falle, die von ASI erstellt wurde. Wenn eine neue Zeile zwischen return und dem zurückgegebenen Ausdruck return \n expression steht, fügt ASI automatisch ein Semikolon vor der neuen Zeile return; \n expression.

Was bedeutet es innerhalb einer Funktion, eine return; -Anweisung zu haben? Die Funktion gibt undefined zurück. Wenn Sie den Mechanismus von ASI nicht im Detail kennen, ist das unerwartet zurückgegebene undefined irreführend.

Untersuchen wir beispielsweise den zurückgegebenen Wert des Aufrufs getPrimeNumbers():

Zwischen der Anweisung return und dem Literalausdruck des Arrays existiert eine neue Zeile. JavaScript fügt nach return automatisch ein Semikolon ein und interpretiert den Code wie folgt:

Die Anweisung return; bewirkt, dass die Funktion getPrimeNumbers() undefined anstelle des erwarteten Arrays zurückgibt.

Das Problem wird gelöst, indem die neue Zeile zwischen return und Array-Literal entfernt wird:

Ich empfehle zu untersuchen, wie genau das automatische Einfügen von Semikolons funktioniert, um solche Situationen zu vermeiden.

Setzen Sie natürlich niemals eine neue Zeile zwischen return und dem zurückgegebenen Ausdruck.

2.5 void operator

void <expression> wertet den Ausdruck aus und gibt unabhängig vom Ergebnis undefined zurück der Bewertung.

Ein Anwendungsfall des Operators void besteht darin, die Ausdrucksauswertung auf undefined, basierend auf einigen Nebenwirkungen der Bewertung.

3. undefiniert in Arrays

Sie erhalten undefined, wenn Sie auf ein Array-Element mit einem Index außerhalb der Grenzen zugreifen.

colors Array hat 3 Elemente, daher sind gültige Indizes 0, 1 und 2.

Da die Indizes 5 und -1 keine Array-Elemente enthalten, sind die Accessoren colors und colors sind undefined.

In JavaScript können sogenannte Sparse-Arrays auftreten. Thesen sind Arrays mit Lücken, d. H. Bei einigen Indizes sind keine Elemente definiert.

Wenn innerhalb eines spärlichen Arrays auf eine Lücke (auch als leerer Steckplatz bezeichnet) zugegriffen wird, erhalten Sie auch eine undefined.

Das folgende Beispiel generiert spärliche Arrays und versucht, auf ihre leeren Slots zuzugreifen:

sparse1 wird durch Aufrufen einer Konstruktor mit einem numerischen ersten Argument.Es hat 3 leere Steckplätze.

sparse2 wird mit einem Array-Literal mit dem fehlenden zweiten Element erstellt.

In einem dieser spärlichen Arrays ergibt der Zugriff auf einen leeren Steckplatz undefined.

Um undefined zu vermeiden, müssen Sie beim Arbeiten mit Arrays gültige Array-Indizes verwenden und die Erstellung spärlicher Arrays verhindern.

4. Unterschied zwischen undefiniert und null

Was ist der Hauptunterschied zwischen undefined und null? Beide Sonderwerte implizieren einen leeren Zustand.

undefined repräsentiert den Wert einer Variablen, die noch nicht initialisiert wurde, während null steht für das absichtliche Fehlen eines Objekts.

Lassen Sie uns den Unterschied in einigen Beispielen untersuchen.

Die Variable number ist definiert Es wird jedoch kein Anfangswert zugewiesen:

number Variable ist undefined, was eine nicht initialisierte Variable angibt.

Das gleiche nicht initialisierte Konzept tritt auf, wenn auf eine nicht vorhandene Objekteigenschaft zugegriffen wird:

Weil lastName ist in obj nicht vorhanden. JavaScript wertet obj.lastName bis .

Auf der anderen Seite wissen Sie, dass eine Variable ein Objekt erwartet. Aus irgendeinem Grund können Sie das Objekt jedoch nicht instanziieren. In diesem Fall ist null ein aussagekräftiger Indikator für ein fehlendes Objekt.

Beispielsweise ist clone() eine Funktion, die Klont ein einfaches JavaScript-Objekt. Es wird erwartet, dass die Funktion ein Objekt zurückgibt:

clone() kann jedoch mit einem Nicht-Objekt-Argument aufgerufen werden: 15 oder null. In einem solchen Fall kann die Funktion keinen Klon erstellen und gibt daher null zurück – den Indikator für ein fehlendes Objekt. Der Operator

typeof unterscheidet zwischen undefined und null:

Auch der strenge Qualitätsoperator === unterscheidet von null:

5. Schlussfolgerung

undefined Die Existenz ist eine Folge der zulässigen Natur von JavaScript, die die Verwendung von:

  • nicht initialisierten Variablen
  • nicht vorhandene Objekteigenschaften oder -methoden

  • außerhalb der Grenzen Indizes für den Zugriff auf Array-Elemente
  • das Aufrufergebnis einer Funktion, die nichts zurückgibt

Ein direkter Vergleich mit undefined ist unsicher, da Sie sich auf eine oben erwähnte zulässige, aber entmutigte Praxis verlassen.

Eine effiziente Strategie besteht darin, das Auftreten des Schlüsselworts undefined in Ihrem Code mindestens zu reduzieren, indem Sie gute Gewohnheiten anwenden, z. B.:

  • Reduzieren Sie die Verwendung nicht initialisierter Variablen.
  • Machen Sie den Lebenszyklus der Variablen kurz und nahe an der Quelle ihrer Verwendung.
  • Weisen Sie den Variablen nach Möglichkeit Anfangswerte zu.
  • favor const, andernfalls let
  • Standardwerte für unbedeutende Funktionsparameter verwenden
  • Überprüfen Sie die Eigenschaften Vorhandensein oder Füllen der unsicheren Objekte mit Standardeigenschaften
  • Vermeiden Sie die Verwendung spärlicher Arrays.

Ist es gut, dass JavaScript beide undefined und null, um leere Werte darzustellen?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.