Gestione di valori nulli e indefiniti in JavaScript

Un aspetto dello sviluppo di JavaScript con cui molti sviluppatori hanno difficoltà è la gestione dei valori opzionali. Quali sono le migliori strategie per ridurre al minimo gli errori causati da valori che potrebbero essere null, undefined o altrimenti non inizializzati in fase di esecuzione?

Alcuni linguaggi hanno offerte integrate per queste circostanze. In alcuni linguaggi tipizzati staticamente, puoi dire che null e undefined sono valori illegali e lasciare che il tuo linguaggio di programmazione generi un’eccezione TypeError in fase di compilazione , ma anche in quei linguaggi, ciò non può impedire il flusso di input nulli nel programma in fase di esecuzione.

Per gestire meglio questo problema, dobbiamo capire da dove possono provenire questi valori. Qui sono alcune delle fonti più comuni:

  • Input dell’utente
  • Database / record di rete
  • Stato non inizializzato
  • Funzioni che potrebbero non restituire nulla

Quando hai a che fare con l’input dell’utente, la convalida è la prima e migliore linea di difesa. Spesso mi affido ai validatori di schemi per svolgere questo lavoro. Ad esempio, controlla reagire -jsonschema-form.

Hydrating Records from Input

Passo sempre gli input che ricevo dalla rete, dal database o dall’input dell’utente attraverso una funzione di idratazione. Ad esempio, userò creatori di azioni redux in grado di gestire

valori per idratare i record utente:

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

A volte, dovrai visualizzare cose diverse a seconda dello stato corrente dei dati. Se è possibile visualizzare una pagina prima che tutti i dati siano inizializzati, potresti trovarti in quella situazione. Ad esempio, quando visualizzi i saldi monetari per un utente, potresti visualizzare accidentalmente un saldo di $ 0 prima del caricamento dei dati. Ho visto questo sconvolgere gli utenti diverse volte. È possibile creare tipi di dati personalizzati che generano output diversi in base allo stato corrente:

Il codice sopra è una macchina a stati che rende impossibile visualizzare stati non validi. Quando crei il saldo per la prima volta, verrà impostato su uno stato uninitialized. Se provi a visualizzare un saldo mentre lo stato è uninitialized, otterrai sempre un valore segnaposto (“--“).

Per cambiarlo, devi impostare esplicitamente un valore chiamando il metodo .set o la scorciatoia setBalance abbiamo definito di seguito la createBalance factory.

Lo stato stesso è incapsulato per proteggerlo da interferenze esterne per assicurarsi che altre funzioni non possano afferrarlo e impostarlo in uno stato non valido.

Nota: se ti stai chiedendo perché stiamo usando stringhe invece di numeri per questo, è perché rappresento i tipi di denaro con stringhe di numeri grandi con molta precisione decimale per evitare errori di arrotondamento e rappresentare accuratamente i valori per le transazioni di criptovaluta, che possono avere una precisione decimale significativa arbitraria.

Se si ” usando l’architettura Redux o Redux, puoi dichiarare macchine a stati con Redu x-DSM.

Evita di creare valori nulli e non definiti

Nelle tue funzioni puoi evitare di creare null o undefined valori con cui iniziare. Ci sono un paio di modi per farlo integrati in JavaScript che mi vengono in mente. Vedi sotto.

Evita null

Non creo mai esplicitamente i valori null in JavaScript, perché non ho mai visto il punto di avere due valori diversi valori primitivi che essenzialmente significano “questo valore non esiste”.

Dal 2015, JavaScript supporta i valori predefiniti che vengono inseriti quando non si fornisce un valore per l’argomento o la proprietà in questione. Queste impostazioni predefinite non funzionano per i valori null. Questo di solito è un bug, nella mia esperienza. Per evitare questa trappola, non utilizzare null in JavaScript.

Se desideri casi speciali per valori non inizializzati o vuoti, le macchine a stati sono una soluzione migliore. Vedi sopra.

Nuove funzioni JavaScript

Ci sono un paio di funzioni che possono aiutarti a gestire null o undefined valori. Entrambe sono proposte di fase 3 al momento in cui scrivo, ma se stai leggendo dal futuro, potresti essere in grado di usarle.

Al momento della stesura di questo articolo, il concatenamento opzionale è una proposta di fase 3. Funziona così:

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

Nullish Coalescing Operator

Anche una proposta della fase 3 da aggiungere alla specifica, “nullish coalescing operator “È fondamentalmente un modo elegante per dire” operatore del valore di riserva “. Se il valore a sinistra è undefined o null, restituisce il valore a destra.Funziona in questo modo:

Asynchronous O with Promises

Se una funzione potrebbe non restituire un valore, potrebbe essere una buona idea racchiuderla in un Either. Nella programmazione funzionale, la monade Either è uno speciale tipo di dati astratto che consente di collegare due diversi percorsi di codice: un percorso di successo o un percorso di errore. JavaScript ha un tipo di dati asincrono o monade chiamato Promise. Puoi usarlo per eseguire ramificazioni di errori dichiarativi per valori indefiniti:

Potresti scriverne una versione sincrona se vuoi, ma non ne ho avuto molto bisogno. Lo lascio come esercizio per te. Se hai una buona base in funtori e monadi, il processo sarà più facile. Se questo suona intimidatorio, non preoccuparti. Usa solo le promesse. Sono integrati e funzionano bene la maggior parte del tempo.

Gli array per Maybes

Gli array implementano un metodo map che accetta una funzione che viene applicata a ogni elemento dell’array. Se l’array è vuoto, la funzione non verrà mai chiamata. In altre parole, gli array in JavaScript possono svolgere il ruolo di Maybes da linguaggi come Haskell.

Cos’è un Forse?

Un Forse è uno speciale tipo di dati astratto che incapsula un valore opzionale . Il tipo di dati ha due forme:

  • Solo – Un Forse che contiene un valore
  • Niente – Un Forse senza valore

Ecco il succo dell’idea:

Questo è solo un esempio per dimostrare il concetto. Potresti costruire un’intera libreria di funzioni utili attorno a maybes, implementando altre operazioni come flatMap e flat (ad esempio, per evitare Just(Just(value)) quando componi più funzioni che restituiscono forse). Ma JavaScript ha già un tipo di dati che implementa molte di queste funzionalità out-of-the-box, quindi di solito preferisco quello: The Array.

Se vuoi creare una funzione che può o potrebbe non produrre un risultato (in particolare se può esserci più di un risultato), potresti avere un ottimo caso d’uso per restituire un array.

Trovo che map non verrà richiamato in un elenco vuoto molto utile per evitare i valori null e undefined, ma ricorda, se l’array contiene valori null e undefined, chiamerà la funzione con quei valori, quindi se la funzione che stai eseguendo potrebbe produrre null o undefined, dovrai filtrare quelli dall’array restituito, come dimostrato sopra. Ciò potrebbe avere l’effetto di modificare la lunghezza di la raccolta.

In Haskell, c’è una funzione maybe che (come ) applica una funzione a un valore. Ma il valore è facoltativo e incapsulato in un Maybe. Possiamo utilizzare il tipo di dati JavaScript “s Array per fare essenzialmente la stessa cosa:

maybe accetta un valore di riserva , quindi una funzione da mappare sull’array forse, quindi un array forse (un array contenente un valore o niente) e restituisce il risultato dell’applicazione della funzione al contenuto dell’array o il valore di fallback se l’array è vuoto.

Per comodità, ho anche definito una funzione toMaybeArray e ho utilizzato la funzione maybe per creare è più ovvio per questa dimostrazione.

Se vuoi fare qualcosa di simile nel codice di produzione, ho creato una libreria open source testata per renderlo più facile. Si chiama Maybearray. Il vantaggio di Maybearray rispetto ad altre librerie JavaScript Forse è che utilizza array JavaScript nativi per rappresentare i valori, quindi non devi dare loro alcun trattamento speciale o fare qualcosa di speciale per convertire avanti e indietro. Quando incontri forse array nel tuo debug, non devi chiedere “cos’è questo tipo strano ?!” È solo un array di un valore o un array vuoto e li hai già visti un milione di volte.

Passaggi successivi

Ci sono molti più contenuti su EricElliottJS.com, inclusi molti di video, esercizi, screencast registrati e suggerimenti rapidi. Se non sei iscritto, è il momento ideale per vedere cosa ti sei perso!

Inizia la tua lezione gratuita su EricElliottJS.com

Write a Comment

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *