Omgaan met null en ongedefinieerd in JavaScript

Een aspect van JavaScript-ontwikkeling waar veel ontwikkelaars mee worstelen, is het omgaan met optionele waarden. Wat zijn de beste strategieën om fouten te minimaliseren die worden veroorzaakt door waarden die tijdens runtime null, undefined of anderszins niet-geïnitialiseerd zouden kunnen zijn?

Sommige talen hebben ingebouwde mogelijkheden voor die omstandigheden. In sommige statisch getypeerde talen kun je zeggen dat null en undefined illegale waarden zijn, en laat je programmeertaal een TypeError genereren tijdens het compileren , maar zelfs in die talen kan dat “niet voorkomen dat null-invoer tijdens runtime in het programma stroomt.

Om dit probleem beter onder de knie te krijgen, moeten we begrijpen waar deze waarden vandaan kunnen komen. zijn enkele van de meest voorkomende bronnen:

  • Gebruikersinvoer
  • Database- / netwerkrecords
  • Niet-geïnitialiseerde status
  • Functies die niets teruggeven

Als je te maken hebt met gebruikersinvoer, is validatie de eerste en beste verdedigingslinie. Ik vertrouw vaak op schemavalidators om te helpen met die taak. Kijk bijvoorbeeld eens naar react -jsonschema-form.

Records hydrateren vanuit invoer

Ik geef invoer die ik ontvang van het netwerk, de database of gebruikersinvoer altijd door via een hydraterende functie. Ik gebruik bijvoorbeeld redux actiemakers die

waarden om gebruikersrecords te hydrateren:

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

Soms moet u verschillende dingen weergeven, afhankelijk van de huidige status van de gegevens. Als het mogelijk is om een pagina weer te geven voordat alle gegevens zijn geïnitialiseerd, bevindt u zich mogelijk in die situatie. Als u bijvoorbeeld geldsaldi weergeeft aan een gebruiker, kunt u per ongeluk een saldo van € 0 weergeven voordat de gegevens worden geladen. Ik heb gebruikers een aantal keer van streek zien maken. U kunt aangepaste gegevenstypen maken die verschillende uitvoer genereren op basis van de huidige toestand:

De bovenstaande code is een toestandsmachine die het onmogelijk maakt om ongeldige toestanden weer te geven. Wanneer u het saldo voor het eerst aanmaakt, wordt het in de status uninitialized gezet. Als u een saldo probeert weer te geven terwijl de staat uninitialized is, krijgt u in plaats daarvan altijd een tijdelijke aanduiding voor de waarde (“--“).

Om dat te veranderen, moet je expliciet een waarde instellen door de .set methode aan te roepen, of de setBalance snelkoppeling we hebben hieronder de createBalance fabriek gedefinieerd.

De staat zelf is ingekapseld om deze te beschermen tegen inmenging van buitenaf om ervoor te zorgen dat andere functies het niet kunnen pakken en instellen naar een ongeldige staat.

Opmerking: als je je afvraagt waarom we hiervoor strings gebruiken in plaats van getallen, komt dat omdat ik geldsoorten vertegenwoordig met reeksen met grote getallen met veel decimale precisie om afrondingsfouten te voorkomen en nauwkeurig waarden voor cryptocurrency-transacties weer te geven, die een willekeurige significante decimale precisie kunnen hebben.

Als je ‘ Als u de Redux- of Redux-architectuur gebruikt, kunt u state-machines declareren met Redu x-DSM.

Vermijd het maken van null en ongedefinieerde waarden

In uw eigen functies kunt u voorkomen dat u null of undefined waarden om mee te beginnen. Er zijn een paar manieren om dat in JavaScript te doen die in je opkomen. Zie hieronder.

Vermijd null

Ik maak nooit expliciet null waarden in JavaScript, omdat ik nooit het nut heb ingezien van twee verschillende primitieve waarden die in wezen betekenen “deze waarde bestaat niet.”

Sinds 2015 ondersteunt JavaScript standaardwaarden die worden ingevuld wanneer u geen waarde opgeeft voor het argument of de eigenschap in kwestie. Deze standaardinstellingen werken niet voor null -waarden. Dat is meestal een fout, in mijn ervaring. Om die valstrik te vermijden, gebruik null niet in JavaScript.

Als je speciale gevallen wilt voor niet-geïnitialiseerde of lege waarden, zijn staatsautomaten een betere gok. Zie hierboven.

Nieuwe JavaScript-functies

Er zijn een aantal functies die u kunnen helpen omgaan met null of undefined waarden. Beide zijn fase 3 voorstellen op het moment van schrijven, maar als je “aan het lezen bent uit de toekomst, kun je ze misschien gebruiken.

Op het moment van schrijven is optionele chaining een fase 3 voorstel. Het werkt als volgt:

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

Nullish Coalescing Operator

Ook een voorstel van fase 3 dat aan de specificatie moet worden toegevoegd, “nullish coalescing operator “Is in feite een mooie manier om” fallback value-operator “te zeggen. Als de waarde aan de linkerkant undefined of null is, resulteert dit in de waarde aan de rechterkant.Het werkt als volgt:

Asynchroon ofwel met beloften

Als een functie misschien niet terugkomt met een waarde, kan het een goed idee zijn om deze in een ofwel te stoppen. Bij functioneel programmeren is de monade Ofwel een speciaal abstract gegevenstype waarmee u twee verschillende codepaden kunt koppelen: een succespad of een faalpad. JavaScript heeft een ingebouwd asynchroon ofwel monad-achtig gegevenstype genaamd Promise. Je kunt het gebruiken om declaratieve vertakkingen voor ongedefinieerde waarden uit te voeren:

Je zou daar een synchrone versie van kunnen schrijven als je wilt, maar ik heb het niet veel nodig. Ik laat dat als oefening voor je over. Als je een goede basis hebt in functoren en monaden, zal het proces gemakkelijker zijn. Als dat intimiderend klinkt, maak je er dan geen zorgen over. Gebruik gewoon beloften. Ze zijn ingebouwd en werken meestal prima.

Arrays voor Maybes

Arrays implementeren een map -methode die een functie die wordt toegepast op elk element van de array. Als de array leeg is, wordt de functie nooit aangeroepen. Met andere woorden, arrays in JavaScript kunnen de rol van Maybes vervullen vanuit talen zoals Haskell.

Wat is een misschien?

Een misschien is een speciaal abstract gegevenstype dat een optionele waarde omvat . Het gegevenstype heeft twee vormen:

  • Gewoon – A Misschien dat een waarde bevat
  • Niets – a Misschien zonder waarde

Hier is de kern van het idee:

Dit is slechts een voorbeeld om het concept te demonstreren. Je zou een hele bibliotheek met handige functies kunnen bouwen rond maybes, door andere bewerkingen te implementeren zoals flatMap en flat (bijvoorbeeld om Just(Just(value)) wanneer u meerdere misschien-terugkerende functies samenstelt). Maar JavaScript heeft al een gegevenstype dat veel van die functies out-of-the-box implementeert, dus ik grijp daar meestal naar: The Array.

Als je een functie wilt maken die kan of levert misschien geen resultaat op (vooral als er meer dan één resultaat kan zijn), je hebt misschien een goede use-case om een array te retourneren.

Ik vind het feit dat map zal “niet worden aangeroepen op een lege lijst, erg handig om null en undefined waarden te vermijden, maar onthoud dat als de array bevat null en undefined waarden, zal het de functie aanroepen met die waarden, dus als de functie die je uitvoert null of undefined, “zul je die uit je geretourneerde array moeten filteren, zoals hierboven is aangetoond. Dat kan tot gevolg hebben dat de lengte van de verzameling.

In Haskell is er een functie maybe die (zoals ) past een functie toe op een waarde. Maar de waarde is optioneel en ingekapseld in een Maybe. We kunnen JavaScript “s Array gegevenstype gebruiken om in wezen hetzelfde te doen:

maybe neemt een reserve-waarde , dan een functie om de misschien-array toe te wijzen, dan een misschien-array (een array met één waarde, of niets), en retourneert ofwel het resultaat van het toepassen van de functie op de inhoud van de array, of de terugvalwaarde als de array is leeg.

Gemakshalve heb ik ook een toMaybeArray -functie gedefinieerd en de maybe -functie gemaakt om het meest voor de hand liggend voor deze demonstratie.

Als je zoiets als dit in productiecode wilt doen, heb ik een unit-geteste open source-bibliotheek gemaakt om het gemakkelijker te maken. Het heet Maybearray. Het voordeel van Maybearray ten opzichte van andere JavaScript Misschien-bibliotheken is dat het native JavaScript-arrays gebruikt om waarden weer te geven, zodat u ze geen speciale behandeling hoeft te geven of iets speciaals hoeft te doen om heen en weer te converteren. Wanneer u misschien-arrays tegenkomt tijdens het debuggen, hoeft u niet te vragen: “wat is dit rare type ?!” Het is gewoon een array van een waarde of een lege array en je hebt ze al een miljoen keer eerder gezien.

Volgende stappen

Er is veel meer inhoud op EricElliottJS.com, waaronder veel van video’s, oefeningen, opgenomen screencasts en snelle tips. Als je geen lid bent, is dit een goed moment om te zien wat je hebt gemist!

Start uw gratis les op EricElliottJS.com

Write a Comment

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *