Ein Aspekt der JavaScript-Entwicklung, mit dem viele Entwickler zu kämpfen haben, ist der Umgang mit optionalen Werten. Was sind die besten Strategien, um Fehler zu minimieren, die durch Werte verursacht werden, die null
, undefined
oder zur Laufzeit nicht initialisiert sein können?
Einige Sprachen verfügen über integrierte Vergünstigungen für diese Umstände. In einigen statisch typisierten Sprachen können Sie sagen, dass null
und undefined
unzulässige Werte sind, und Ihre Programmiersprache beim Kompilieren einen TypeError auslösen lassen Aber selbst in diesen Sprachen kann dies nicht verhindern, dass zur Laufzeit Null-Eingaben in das Programm fließen.
Um dieses Problem besser in den Griff zu bekommen, müssen wir verstehen, woher diese Werte stammen können sind einige der häufigsten Quellen:
- Benutzereingabe
- Datenbank- / Netzwerkdatensätze
- Nicht initialisierter Status
- Funktionen, die dies könnten nichts zurückgeben
Wenn Sie mit Benutzereingaben zu tun haben, ist die Validierung die erste und beste Verteidigungslinie. Ich verlasse mich häufig auf Schema-Validatoren, um bei diesem Job zu helfen -jsonschema-form.
Hydrating Records from Input
Ich übergebe Eingaben, die ich vom Netzwerk, der Datenbank oder Benutzereingaben erhalte, immer über eine Hydrating-Funktion. Zum Beispiel werde ich verwenden Redux-Aktionsersteller, die
-Werte, um Benutzerdatensätze zu hydratisieren:
const setUser = ({ name = "Anonymous", avatar = "anon.png" } = {}) => ({
type: setUser.type,
payload: {
name,
avatar
}
});
setUser.type = "userReducer/setUser";
Manchmal müssen Sie je nach aktuellem Status unterschiedliche Dinge anzeigen der Daten. Wenn es möglich ist, eine Seite anzuzeigen, bevor alle Daten initialisiert wurden, befinden Sie sich möglicherweise in dieser Situation. Wenn Sie beispielsweise einem Benutzer Geldguthaben anzeigen, können Sie versehentlich ein Guthaben von 0 USD anzeigen, bevor die Daten geladen werden. Ich habe diese verärgerten Benutzer mehrmals gesehen. Sie können benutzerdefinierte Datentypen erstellen, die basierend auf dem aktuellen Status unterschiedliche Ausgaben generieren:
Der obige Code ist eine Zustandsmaschine, die es unmöglich macht, ungültige Zustände anzuzeigen. Wenn Sie die Waage zum ersten Mal erstellen, wird sie auf den Status uninitialized
gesetzt. Wenn Sie versuchen, ein Guthaben anzuzeigen, während der Status uninitialized
lautet, erhalten Sie stattdessen immer einen Platzhalterwert („--
„).
Um dies zu ändern, müssen Sie einen Wert explizit festlegen, indem Sie die Methode .set
oder die Verknüpfung setBalance
aufrufen Wir haben unten die createBalance
-Fabrik definiert.
Der Status selbst ist gekapselt, um ihn vor Störungen von außen zu schützen und sicherzustellen, dass andere Funktionen ihn nicht erfassen und einstellen können in einen ungültigen Zustand.
Hinweis: Wenn Sie sich fragen, warum wir dafür Zeichenfolgen anstelle von Zahlen verwenden, liegt dies daran, dass ich Geldarten mit darstelle Zeichenfolgen mit großen Zahlen und hoher Dezimalgenauigkeit, um Rundungsfehler zu vermeiden und Werte für Kryptowährungstransaktionen genau darzustellen, die eine beliebige signifikante Dezimalgenauigkeit aufweisen können.
Wenn Sie ‚ Bei Verwendung der Redux- oder Redux-Architektur können Sie Zustandsautomaten mit Redu deklarieren x-DSM.
Vermeiden Sie das Erstellen von Null- und undefinierten Werten.
In Ihren eigenen Funktionen können Sie das Erstellen von null
oder undefined
Werte zunächst. Es gibt einige Möglichkeiten, dies in JavaScript zu tun, die mir in den Sinn kommen. Siehe unten.
Vermeiden Sie Null
Ich erstelle niemals explizit null
-Werte in JavaScript, da ich nie wirklich den Sinn gesehen habe, zwei verschiedene Werte zu haben Grundwerte, die im Wesentlichen bedeuten, dass „dieser Wert nicht vorhanden ist“.
Seit 2015 unterstützt JavaScript Standardwerte, die ausgefüllt werden, wenn Sie keinen Wert für das betreffende Argument oder die betreffende Eigenschaft angeben. Diese Standardeinstellungen funktionieren nicht für null
-Werte. Das ist meiner Erfahrung nach normalerweise ein Fehler. Um diese Falle zu vermeiden, verwenden Sie in JavaScript nicht null
.
Wenn Sie Sonderfälle für nicht initialisierte oder leere Werte wünschen, sind Zustandsautomaten die bessere Wahl. Siehe oben.
Neue JavaScript-Funktionen
Es gibt einige Funktionen, mit denen Sie null
oder -Werte. Beide sind zum Zeitpunkt des Schreibens Vorschläge der Stufe 3, aber wenn Sie aus der Zukunft lesen, können Sie sie möglicherweise verwenden.
Zum jetzigen Zeitpunkt ist die optionale Verkettung ein Vorschlag der Stufe 3. Dies funktioniert folgendermaßen:
const foo = {};
// console.log(foo.bar.baz); // throws error
console.log(foo.bar?.baz) // undefined
Nullish Coalescing Operator
Auch ein Vorschlag der Stufe 3, der der Spezifikation „Nullish Coalescing Operator“ hinzugefügt werden soll „Ist im Grunde eine ausgefallene Art,“ Fallback-Wertoperator „zu sagen. Wenn der Wert auf der linken Seite undefined
oder null
ist, wird er ausgewertet der Wert auf der rechten Seite.Dies funktioniert folgendermaßen:
Asynchron entweder mit Versprechungen
Wenn eine Funktion möglicherweise nicht mit einem Wert zurückgegeben wird, ist es möglicherweise eine gute Idee, sie in ein Entweder zu verpacken. Bei der funktionalen Programmierung ist die Entweder-Monade ein spezieller abstrakter Datentyp, mit dem Sie zwei verschiedene Codepfade anhängen können: einen Erfolgspfad oder einen Fehlerpfad. JavaScript verfügt über einen integrierten asynchronen monadischen Datentyp namens Promise. Sie können es verwenden, um deklarative Fehler für undefinierte Werte zu verzweigen:
Sie können eine synchrone Version davon schreiben, wenn Sie möchten, aber ich habe es nicht viel gebraucht. Ich werde das als Übung für Sie belassen. Wenn Sie eine gute Grundlage in Funktoren und Monaden haben, wird der Prozess einfacher. Wenn das einschüchternd klingt, mach dir keine Sorgen. Verwenden Sie einfach Versprechen. Sie sind integriert und funktionieren die meiste Zeit einwandfrei.
Arrays für Maybes
Arrays implementieren eine map
-Methode, die erforderlich ist Eine Funktion, die auf jedes Element des Arrays angewendet wird. Wenn das Array leer ist, wird die Funktion niemals aufgerufen. Mit anderen Worten, Arrays in JavaScript können die Rolle von Maybes aus Sprachen wie Haskell übernehmen.
Was ist ein Vielleicht?
A Vielleicht ist ein spezieller abstrakter Datentyp, der einen optionalen Wert kapselt . Der Datentyp hat zwei Formen:
- Nur – Ein Vielleicht, das einen Wert enthält
- Nichts – ein Vielleicht ohne Wert
Hier ist der Kern der Idee:
Dies ist nur ein Beispiel, um das Konzept zu demonstrieren. Sie können eine ganze Bibliothek nützlicher Funktionen um maybes herum erstellen und andere Operationen wie flatMap
und flat
implementieren (z. B. um Just(Just(value))
, wenn Sie mehrere Funktionen erstellen, die möglicherweise zurückgegeben werden). Aber JavaScript hat bereits einen Datentyp, der viele dieser Funktionen sofort implementiert. Daher greife ich normalerweise stattdessen dazu: Das Array.
Wenn Sie eine Funktion erstellen möchten, die möglicherweise oder Wenn Sie möglicherweise kein Ergebnis erzielen (insbesondere wenn es mehr als ein Ergebnis geben kann), haben Sie möglicherweise einen guten Anwendungsfall, um ein Array zurückzugeben.
Ich finde die Tatsache, dass map
wird nicht in einer leeren Liste aufgerufen, was sehr nützlich ist, um null
und undefined
Werte zu vermeiden, aber denken Sie daran, ob das Array enthält null
und undefined
Werte, ruft die Funktion mit diesen Werten auf. Wenn also die von Ihnen ausgeführte Funktion null
oder undefined
müssen Sie diese aus Ihrem zurückgegebenen Array herausfiltern, wie oben gezeigt. Dies kann die Länge von ändern die Sammlung.
In Haskell gibt es eine Funktion maybe
, die (wie ) wendet eine Funktion auf einen Wert an. Der Wert ist jedoch optional und in einem Maybe
gekapselt. Wir können den Datentyp Array
von JavaScript verwenden, um im Wesentlichen dasselbe zu tun:
maybe
nimmt einen Fallback-Wert an , dann eine Funktion zum Zuordnen über das Vielleicht-Array, dann ein Vielleicht-Array (ein Array, das einen Wert oder nichts enthält) und gibt entweder das Ergebnis der Anwendung der Funktion auf den Inhalt des Arrays oder den Fallback-Wert zurück, wenn das Array ist leer.
Der Einfachheit halber habe ich auch eine toMaybeArray
-Funktion definiert und die maybe
-Funktion ausgeführt Dies ist für diese Demonstration am offensichtlichsten.
Wenn Sie so etwas im Produktionscode ausführen möchten, habe ich eine Unit-getestete Open-Source-Bibliothek erstellt, um dies zu vereinfachen. Es heißt Maybearray. Der Vorteil von Maybearray gegenüber anderen JavaScript-Bibliotheken besteht möglicherweise darin, dass native JavaScript-Arrays zur Darstellung von Werten verwendet werden, sodass Sie ihnen keine besondere Behandlung geben oder etwas Besonderes tun müssen, um hin und her zu konvertieren. Wenn Sie beim Debuggen auf Vielleicht Arrays stoßen, müssen Sie nicht fragen: „Was ist dieser seltsame Typ?!“ Es ist nur ein Array eines Werts oder eines leeren Arrays, und Sie haben sie bereits millionenfach gesehen.
Nächste Schritte
Auf EricElliottJS.com gibt es viel mehr Inhalte, einschließlich Lose Wenn Sie kein Mitglied sind, ist jetzt ein guter Zeitpunkt, um zu sehen, was Sie vermisst haben!