Håndtering null og udefinert i JavaScript

Et aspekt ved JavaScript-utvikling som mange utviklere sliter med, er å håndtere valgfrie verdier. Hva er de beste strategiene for å minimere feil forårsaket av verdier som kan være null, undefined, eller på annen måte ikke initialiseres ved kjøretid?

Noen språk har innebygde overkommelser for disse omstendighetene. I noen statisk typede språk kan du si at null og undefined er ulovlige verdier, og la programmeringsspråket ditt kaste en TypeError på kompileringstidspunktet , men selv på disse språkene, kan det ikke forhindre at nullinnganger strømmer inn i programmet ved kjøretid.

For å få et bedre håndtak på dette problemet, må vi forstå hvor disse verdiene kan komme fra. Her er noen av de vanligste kildene:

  • Brukerinngang
  • Database- / nettverksposter
  • Ikke-initialisert tilstand
  • Funksjoner som kan returner ingenting

Når du har å gjøre med brukerinndata, er validering den første og beste forsvarslinjen. Jeg stoler ofte på skjemavalidatorer for å hjelpe med den jobben. Sjekk for eksempel ut reagerer -jsonschema-form.

Hydrating Records from Input

Jeg sender alltid innganger jeg mottar fra nettverket, databasen eller brukerinngangen gjennom en hydratiseringsfunksjon. For eksempel vil jeg bruke redux action skapere som kan håndtere

verdier for å hydrere brukeroppføringer:

const setUser = ({ name = "Anonymous", avatar = "anon.png" } = {}) => ({
type: setUser.type,
payload: {
name,
avatar
}
});
setUser.type = "userReducer/setUser";

Noen ganger må du vise forskjellige ting avhengig av gjeldende tilstand av dataene. Hvis det er mulig å vise en side før alle dataene initialiseres, kan du komme i den situasjonen. For eksempel når du viser pengesaldoer til en bruker, kan du ved et uhell vise en saldo på $ 0 før dataene lastes inn. Jeg har sett dette opprøre brukere flere ganger. Du kan opprette egendefinerte datatyper som genererer forskjellige utganger basert på gjeldende tilstand:

Koden ovenfor er en tilstandsmaskin som gjør det umulig å vise ugyldige tilstander. Når du først oppretter saldoen, blir den satt til en uninitialized -tilstand. Hvis du prøver å vise en saldo mens tilstanden er uninitialized, får du alltid en plassholderverdi («--«) i stedet.

For å endre det, må du angi en verdi eksplisitt ved å ringe .set -metoden, eller setBalance snarveien vi definerte under createBalance fabrikken.

Selve staten er innkapslet for å beskytte den mot interferens utenfor for å sikre at andre funksjoner ikke kan gripe den og sette den til en ugyldig tilstand.

Merk: Hvis du lurer på hvorfor vi bruker strenger i stedet for tall for dette, er det fordi jeg representerer pengetyper med store tallstrenger med mye desimal presisjon for å unngå avrundingsfeil og nøyaktig representere verdier for kryptokurrency transaksjoner, som kan ha vilkårlig betydelig desimal presisjon.

Hvis du ‘ Hvis du bruker Redux eller Redux-arkitektur, kan du erklære tilstandsmaskiner med Redu x-DSM.

Unngå å opprette null og udefinerte verdier

I dine egne funksjoner kan du unngå å lage null eller undefined verdier til å begynne med. Det er noen måter å gjøre det innebygd i JavaScript som kommer i tankene. Se nedenfor.

Unngå null

Jeg oppretter aldri eksplisitt null verdier i JavaScript, fordi jeg aldri virkelig så poenget med å ha to forskjellige primitive verdier som egentlig betyr «denne verdien eksisterer ikke.»

Siden 2015 har JavaScript støttet standardverdier som fylles ut når du ikke oppgir en verdi for argumentet eller egenskapen det gjelder. Disse standardene fungerer ikke for null verdier. Det er vanligvis en feil etter min erfaring. For å unngå denne fellen, bruk ikke null i JavaScript.

Hvis du vil ha spesielle tilfeller for ikke-initialiserte eller tomme verdier, er tilstandsmaskiner en bedre innsats. Se ovenfor.

Nye JavaScript-funksjoner

Det er et par funksjoner som kan hjelpe deg med å håndtere null eller undefined verdier. Begge er trinn 3-forslag i skrivende stund, men hvis du leser fra fremtiden, kan du kanskje bruke dem.

I skrivende stund er valgfri kjetting et trinn 3-forslag. Det fungerer slik:

const foo = {};
// console.log(foo.bar.baz); // throws error
console.log(foo.bar?.baz) // undefined

Nullish Coalescing Operator

Også et trinn 3-forslag som skal legges til spesifikasjonen, «nullish coalescing operator ”Er i utgangspunktet en fancy måte å si» reserveverdioperatør «. Hvis verdien til venstre er undefined eller null, evalueres den til verdien til høyre.Det fungerer slik:

Asynkron enten med løfter

Hvis en funksjon kanskje ikke kommer tilbake med en verdi, kan det være lurt å pakke den inn i en av dem. I funksjonell programmering er Enten monaden en spesiell abstrakt datatype som lar deg legge til to forskjellige kodestier: en suksessbane eller en mislykkelsesbane. JavaScript har en innebygd asynkron Enten monadisk datatype som heter Promise. Du kan bruke den til å gjøre deklarative feilgrener for udefinerte verdier:

Du kan skrive en synkron versjon av det hvis du vil, men jeg har ikke hatt behov for det mye. Jeg lar det være som en øvelse for deg. Hvis du har god forankring i funksjoner og monader, vil prosessen bli enklere. Hvis det høres skremmende ut, ikke bekymre deg for det. Bare bruk løfter. De er innebygd og fungerer bra det meste av tiden.

Arrays for Maybes

Arrays implementerer en map -metode som tar en funksjon som brukes på hvert element i matrisen. Hvis matrisen er tom, vil funksjonen aldri kalles. Med andre ord kan Arrays i JavaScript fylle Maybes rolle fra språk som Haskell.

Hva er en kanskje?

A Kanskje er en spesiell abstrakt datatype som innkapsler en valgfri verdi . Datatypen tar to former:

  • Bare – A Kanskje som inneholder en verdi
  • Ingenting – en kanskje uten verdi

Her er kjernen i ideen:

Dette er bare et eksempel for å demonstrere konseptet. Du kan bygge et helt bibliotek med nyttige funksjoner rundt maybes, og implementere andre operasjoner som flatMap og flat (f.eks. For å unngå Just(Just(value)) når du komponerer flere kanskje-returnerende funksjoner). Men JavaScript har allerede en datatype som implementerer mange av disse funksjonene utenom boksen, så jeg strekker meg vanligvis etter det i stedet: Array.

Hvis du vil lage en funksjon som kan eller kan ikke gi et resultat (spesielt hvis det kan være mer enn ett resultat), kan det hende du har en god bruksområde for å returnere en matrise.

Jeg finner det faktum at map vil ikke bli kalt på en tom liste som er veldig nyttig for å unngå null og undefined verdier, men husk hvis matrisen inneholder null og undefined verdier, vil det kalle funksjonen med disse verdiene, så hvis funksjonen du kjører kan produsere null eller undefined, du må filtrere dem ut av den returnerte matrisen, som vist ovenfor. Det kan ha effekten av å endre lengden på samlingen.

I Haskell er det en funksjon maybe som (som ) bruker en funksjon til en verdi. Men verdien er valgfri og innkapslet i en Maybe. Vi kan bruke JavaScript «s Array datatype for å gjøre det samme:

maybe tar en reserveverdi , deretter en funksjon for å kartlegge over kanskje matrisen, deretter en kanskje matrise (en matrise som inneholder en verdi, eller ingenting), og returnerer enten resultatet av å bruke funksjonen til matrisenes innhold, eller reserveverdien hvis matrisen er tom.

For enkelhets skyld har jeg også definert en toMaybeArray -funksjon, og curried maybe -funksjonen for å lage det er mest åpenbart for denne demonstrasjonen.

Hvis du vil gjøre noe slikt i produksjonskoden, har jeg laget et enhetstestet open source-bibliotek for å gjøre det lettere. Det heter Maybearray. Fordelen med Maybearray fremfor andre JavaScript Kanskje biblioteker er at den bruker native JavaScript-arrays for å representere verdier, slik at du ikke trenger å gi dem noen spesiell behandling eller gjøre noe spesielt for å konvertere frem og tilbake. Når du støter på kanskje arrays i feilsøkingen din, trenger du ikke spørre: «Hva er denne rare typen ?!» Det er bare en matrise med en verdi eller en tom matrise, og du har sett dem en million ganger før.

Neste trinn

Det er mye mer innhold på EricElliottJS.com, inkludert mye med videoer, øvelser, innspilte screencasts og raske tips. Hvis du ikke er medlem, er det en flott tid å se hva du har savnet!

Start din gratis leksjon på EricElliottJS.com

Write a Comment

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *