Gestionarea nulă și nedefinită în JavaScript

Un aspect al dezvoltării JavaScript cu care se luptă mulți dezvoltatori este tratarea valorilor opționale. Care sunt cele mai bune strategii pentru a minimiza erorile cauzate de valori care ar putea fi null, undefined sau altfel neinitializate în timpul rulării?

Unele limbi au încorporate în aceste circumstanțe. În unele limbaje tipizate static, puteți spune că null și undefined sunt valori ilegale și lăsați limbajul de programare să lanseze un TypeError la momentul compilării , dar chiar și în aceste limbi, acest lucru nu poate împiedica fluxul de intrări nule în program în timpul rulării.

Pentru a obține o mai bună abordare a acestei probleme, trebuie să înțelegem de unde pot veni aceste valori. Aici sunt unele dintre cele mai frecvente surse:

  • Introducere utilizator
  • Înregistrări de baze de date / rețea
  • Stare neinițializată
  • Funcții care ar putea nu returnează nimic

Când ai de-a face cu introducerea utilizatorului, validarea este prima și cea mai bună linie de apărare. Mă bazez adesea pe validatori de schemă pentru a ajuta la acea sarcină. De exemplu, verifică reacționează -jsonschema-form.

Hidratarea înregistrărilor de la intrare

Trec întotdeauna intrările pe care le primesc de la rețea, bază de date sau intrări de utilizator printr-o funcție de hidratare. De exemplu, voi folosi creatori de acțiune redux care pot gestiona

valori pentru a hidrata înregistrările utilizatorilor:

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

Uneori, va trebui să afișați lucruri diferite în funcție de starea actuală a datelor. Dacă este posibil să afișați o pagină înainte ca toate datele să fie inițializate, s-ar putea să vă aflați în acea situație. De exemplu, când afișați solduri de bani unui utilizator, puteți afișa accidental un sold de 0 USD înainte de încărcarea datelor. Am văzut acest lucru supărat de mai multe ori pe utilizatori. Puteți crea tipuri de date personalizate care generează rezultate diferite pe baza stării curente:

Codul de mai sus este o mașină de stări care face imposibilă afișarea stărilor nevalide. Când creați pentru prima dată soldul, acesta va fi setat la o stare uninitialized. Dacă încercați să afișați un sold în timp ce starea este uninitialized, veți obține întotdeauna o valoare de substituent („--„).

Pentru a schimba acest lucru, trebuie să setați în mod explicit o valoare apelând metoda .set sau comanda rapidă setBalance am definit mai jos fabrica createBalance.

Statul însuși este încapsulat pentru a-l proteja de interferențele exterioare pentru a ne asigura că alte funcții nu îl pot apuca și seta într-o stare nevalidă.

Notă: Dacă vă întrebați de ce folosim șiruri în loc de numere pentru asta, este pentru că reprezintă tipurile de bani cu șiruri de număr mare cu multă precizie zecimală pentru a evita erorile de rotunjire și pentru a reprezenta cu exactitate valorile pentru tranzacțiile cu criptomonede, care pot avea o precizie zecimală semnificativă arbitrară.

folosind arhitectura Redux sau Redux, puteți declara mașini de stat cu Redu x-DSM.

Evitați crearea de valori nule și nedefinite

În propriile funcții, puteți evita crearea null sau undefined valori pentru început. Există câteva modalități de a face acest lucru încorporat în JavaScript, care îmi vin în minte. Vedeți mai jos.

Evitați nul

Nu creez niciodată în mod explicit valori null în JavaScript, deoarece nu am văzut cu adevărat rostul de a avea două diferite valori primitive care înseamnă în esență „această valoare nu există.”

Din 2015, JavaScript acceptă valorile implicite care se completează atunci când nu furnizați o valoare pentru argumentul sau proprietatea în cauză. Aceste valori implicite nu funcționează pentru valori null. Din experiența mea, aceasta este de obicei o eroare. Pentru a evita această capcană, nu utilizați null în JavaScript.

Dacă doriți cazuri speciale pentru valori neinițializate sau goale, mașinile de stat sunt un pariu mai bun. Vedeți mai sus.

Funcții JavaScript noi

Există câteva funcții care vă pot ajuta să vă ocupați de null sau undefined valori. Ambele sunt propuneri în etapa 3 în momentul redactării acestei lucrări, dar dacă citiți din viitor, este posibil să le puteți folosi.

Începând cu această scriere, înlănțuirea opțională este o propunere în etapa 3. Funcționează astfel:

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

Nullish Coalescing Operator

De asemenea, o propunere de etapa 3 care trebuie adăugată la caietul de sarcini, „operator de coalescence nul ”Este în esență un mod elegant de a spune„ operator de rezervă ”. Dacă valoarea din stânga este undefined sau null, se evaluează la valoarea din dreapta.Funcționează astfel:

Asincron Fie cu promisiuni

Dacă este posibil ca o funcție să nu revină cu o valoare, ar putea fi o idee bună să o înfășurați într-o Fie. În programarea funcțională, oricare monadă este un tip special de date abstracte care vă permite să atașați două căi de cod diferite: o cale de succes sau o cale de eșec. JavaScript are un tip asincron încorporat Fie tip de date monad-ish numit Promise. Puteți să-l utilizați pentru a face o ramificare declarativă a erorilor pentru valori nedefinite:

Ați putea scrie o versiune sincronă a acesteia dacă doriți, dar nu prea am avut nevoie de ea. O voi lăsa ca exercițiu pentru tine. Dacă aveți o bază bună la funcționare și monade, procesul va fi mai ușor. Dacă sună intimidant, nu vă faceți griji. Folosește doar promisiuni. Sunt încorporate și funcționează bine de cele mai multe ori.

Matrice pentru Maybes

Matrice implementează o metodă map care necesită o funcție care se aplică fiecărui element al tabloului. Dacă matricea este goală, funcția nu va fi apelată niciodată. Cu alte cuvinte, matricile în JavaScript pot ocupa rolul Maybes din limbi precum Haskell.

Ce este un Poate?

O Poate este un tip de date abstract special care încapsulează o valoare opțională . Tipul de date ia două forme:

  • Doar – O Poate că conține o valoare
  • Nimic – o Poate fără valoare

Iată esența ideii:

Acesta este doar un exemplu pentru a demonstra conceptul. Puteți construi o întreagă bibliotecă de funcții utile în jurul maybes, implementând alte operații precum flatMap și flat (de exemplu, pentru a evita Just(Just(value)) atunci când compuneți mai multe funcții Poate-returnate). Dar JavaScript are deja un tip de date care implementează o mulțime de acele caracteristici out-of-the-box, așa că, de obicei, ajung la asta: Array.

Dacă doriți să creați o funcție care poate sau s-ar putea să nu producă un rezultat (mai ales dacă pot fi mai multe rezultate), este posibil să aveți un caz de utilizare excelent pentru a returna o matrice.

Constat faptul că map nu va fi apelat pe o listă goală foarte util pentru a evita valorile null și undefined, dar rețineți, dacă matricea conține valori null și undefined, va apela funcția cu acele valori, deci dacă funcția pe care o executați ar putea produce null sau undefined, va trebui să le filtrați din matricea returnată, așa cum s-a demonstrat mai sus. Acest lucru ar putea avea ca efect schimbarea lungimii colecția.

În Haskell, există o funcție maybe care (cum ar fi ) aplică o funcție unei valori. Dar valoarea este opțională și este încapsulată într-un Maybe. Putem folosi tipul de date JavaScript „s Array pentru a face în esență același lucru:

maybe ia o valoare de rezervă , apoi o funcție pentru maparea peste tabloul poate, apoi un tablou poate (un tablou care conține o valoare sau nimic) și returnează fie rezultatul aplicării funcției la conținutul tabloului, fie valoarea de rezervă dacă matricea este gol.

Pentru comoditate, am definit și o funcție toMaybeArray și am redat funcția maybe pentru a face este cel mai evident pentru această demonstrație.

Dacă doriți să faceți așa ceva în codul de producție, am creat o bibliotecă open source testată pe unitate, pentru ao ușura. Se numește Maybearray. Avantajul Maybearray față de alte JavaScript Poate că bibliotecile este că folosește tablouri JavaScript native pentru a reprezenta valori, deci nu trebuie să le acordați niciun tratament special sau să faceți ceva special pentru a converti înainte și înapoi. Când întâlniți matricele Poate în depanare, nu trebuie să întrebați „ce este acest tip ciudat ?!” Este doar o matrice cu o valoare sau o matrice goală și le-ați mai văzut de un milion de ori.

Pașii următori

Există mult mai mult conținut pe EricElliottJS.com, inclusiv multe de videoclipuri, exerciții, posturi de înregistrare înregistrate și sfaturi rapide. Dacă nu sunteți membru, acum este un moment excelent pentru a vedea ce vă lipsea!

Începeți lecția gratuită pe EricElliottJS.com

Write a Comment

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *