6 caracteristici JavaScript pe care ar trebui să le cunoașteți
Publicat: 2020-09-24Cu puțin peste un an în urmă am vorbit despre cele 5 „noi” funcții JavaScript pe care ar trebui să le cunoașteți pentru a le dezvolta confortabil în Gutenberg. Acolo am învățat ce sunt destructurarea obiectelor și a matricei, cum să creăm funcții de săgeți, ce sunt operatorii de răspândire și de odihnă și așa mai departe. Din fericire, JavaScript are încă o mulțime de funcții care, odată ce vă familiarizați cu ele, vă vor ajuta să scrieți un cod mai inteligibil și mai succint.
Astăzi vă voi arăta șase funcții JavaScript foarte interesante. Operatori, scoping variabil, promisiuni, funcții asincrone... ești gata să le înveți pe toate?
#1 Înlănțuire opțională în JavaScript cu operatorul ?.
Operatorul opțional de înlănțuire permite accesul simplificat la atributele unui obiect atunci când există șansa ca unul să fie undefined sau null . De exemplu, să presupunem că aveți un obiect ca următorul:
const toni = { name: 'Antonio', details: { age: 35, }, }; Pentru a accesa age lui toni , mai întâi ai acces la atributul details și apoi age :
function getAge( person ) { return person.details.age; } Problema pe care o avem în funcția anterioară și sunt sigur că nu este nimic nou pentru tine, este că proprietățile pe care ne așteptăm ca person să le aibă nu sunt întotdeauna acolo. Adică, dacă person sau person.details este undefined , funcția de mai sus va declanșa o eroare de tip:
getAge( toni ); // 35 getAge( {} ); // Uncaught TypeError: person.details is undefinedDe obicei, depășim această problemă adăugând câteva măsuri de siguranță:
function getAge( person ) { if ( ! person ) { return; } if ( ! person.details ) { return; } return person.details.age; } getAge( toni ); // 35 getAge( {} ); // undefined care clar o repară. Din păcate, funcția rezultată este mai complexă și are mult cod zgomotos care ne îndepărtează atenția de la lucrurile care contează cu adevărat. Pentru a reveni pe drumul cel bun și a remedia soluția într-un mod mai simplu, tot ce trebuie să facem este să folosim operatorul opțional de înlănțuire ?. :
function getAge( person ) { return person?.details?.age; } getAge( toni ); // 35 getAge( {} ); // undefined În esență, acest operator ne permite să accesăm fiecare proprietate atâta timp cât nu este undefined sau null . De îndată ce detectează că încercăm să accesăm o proprietate a unui obiect inexistent, returnează undefined .
# 2 Nullish Coalescing Operator ( ?? )
În JavaScript este foarte ușor să setați o valoare implicită unei variabile folosind acest operator: || , dreapta? Gresit! Cu toții am făcut asta, dar poate duce la reacții adverse neașteptate dacă nu ești atent...
De exemplu, să presupunem că avem un selector în magazinul nostru Redux care ne permite să recuperăm o valoare setată de utilizator. Dacă utilizatorul nu a specificat încă o valoare (adică valoarea este undefined ), returnăm o valoare implicită folosind || :
function getValue( state ) { return state.value || 5; }Acum, să vedem câteva exemple de ceea ce am obține cu funcția anterioară după ce utilizatorul a setat o valoare sau alta:
// No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 5 Hopa! Totul a funcționat bine până am ajuns la ultimul caz! Aparent, dacă utilizatorul setează valoarea la 0 , rezultatul funcției devine 5 . De ce? Ei bine, rațiunea este destul de obioasă: x||y returnează y dacă și numai dacă, x este o valoare „falsă”. Acest lucru funcționează de obicei bine, deoarece undefined este o valoare falsă. Dar la fel sunt false sau 0 , de exemplu.
În realitate, am vrut să setăm o valoare default doar atunci când nu există. Deci, putem adăuga o protecție pentru a verifica dacă există sau nu o valoare:
function getValue( state ) { if ( undefined === state.value ) return 5; return state.value; }și putem chiar să-l scriem folosind operatorul ternar dacă ne simțim dornici:
function getValue( state ) { return undefined === state.value ? 5 : state.value; } dar, încă o dată, ambele soluții complică inutil codul. Pentru a atribui o valoare implicită unei variabile, trebuie să folosim operatorul de coalescere nul ?? , care returnează partea dreaptă dacă și numai dacă partea stângă este null sau undefined :
function getValue( state ) { return state.value ?? 5; }si, surpriza-surpriza!, rezultatul este exact ce ne-am dorit:
// No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 0A, și, apropo, poți folosi acest operator combinat cu o misiune. De exemplu, aceasta:
value = value ?? 5;este echivalent cu acesta:
value ??= 5;# 3 Promisiuni și funcții asincrone
Promisele sunt un mecanism implementat în JavaScript care ne permite să ne simplificăm codul sursă atunci când lucrăm cu operații asincrone, adică operațiuni ale căror rezultate nu sunt disponibile imediat. De exemplu, dacă dorim să extragem date de pe serverul nostru, este clar că răspunsul nu va fi instantaneu, deoarece trebuie să așteptăm ca serverul să primească cererea, să o proceseze și să ne trimită răspunsul înapoi.
În versiunile și bibliotecile JavaScript mai vechi (de exemplu, jQuery) obișnuiam să implementăm acest lucru cu apeluri inverse. Ideea a fost destul de simplă: împreună cu cererea în sine, definiți funcția (callback-ul) care ar trebui apelată odată ce răspunsul este disponibil. În acest fel, când operațiunea asincronă (adică preluarea datelor de pe server) se încheie, biblioteca va apela funcția și logica noastră se va relua:
jQuery.ajax( { url: 'https://server.com/wp-json/wp/users/1', success: ( user ) => { console.log( user ); }, } );Dacă declanșăm doar o singură cerere, izolată, această soluție este destul de elegantă și convenabilă. Dar, de îndată ce trebuie să îndeplinim mai multe solicitări, lucrurile se murdăresc rapid. De exemplu, dacă vrem să solicităm doi utilizatori diferiți, ar trebui să imbricați apeluri inverse:

jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/1', success: ( user1 ) => { jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/2', success: ( user2 ) => { console.log( user1, user2 ); }, } ); }, } );Promisiunile sunt soluția la această problemă: dacă obținerea unui anumit rezultat nu este imediată (cum ar fi, de exemplu, când recuperăm ceva de pe un server), putem returna imediat o promisiune JavaScript. Acest obiect este un înveliș al valorii reale și semnifică „promisiunea” că respectiva valoare va fi disponibilă la un moment dat în viitor.
De exemplu, dacă ar fi să rescriem primul nostru fragment folosind promisiuni, ar arăta astfel:
const promise = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); promise.then( ( user ) => console.log( user ) ); După cum puteți vedea, wp.apiFetch trebuie să preia utilizatorul 1 de pe server, dar dă un rezultat imediat. Rezultatul, însă, nu este utilizatorul însuși, ci o promisiune care se va rezolva către utilizator odată ce solicitările sunt finalizate. Prin urmare, tot ce trebuie să facem este să scriem un callback care va procesa răspunsul promisiunii atunci când aceasta va fi rezolvată.
S-ar putea să vă gândiți acum că acest lucru nu este atât de dificil din ceea ce am avut înainte, nu? La urma urmei, încă folosim apeluri inverse... dar puteți vedea cât de util este acest lucru odată ce începem să combinăm mai multe solicitări:
const promise1 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); const promise2 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/2', } ); Promise.all( [ promise1, promise2 ] ).then( ( [ user1, user2 ] ) => console.log( user1, user2 ); ); Folosind promisiuni, am reușit să lansăm două solicitări paralele pentru a prelua utilizatorii 1 și 2 și să folosim Promise.all pentru a aștepta ca ambele promisiuni să se rezolve. Niciun cod spaghetti cu apeluri imbricate implicate.
Ei bine, lucrul grozav despre promisiuni este încă pe cale să vină. Putem folosi niște zahăr sintactic pentru a lucra cu promisiuni JavaScript și pentru a scrie cod asincron care arată, bine, sincron. Tot ce trebuie să faceți este să definiți o funcție asincronă folosind cuvântul cheie asincron și dintr-o dată lucrurile devin mult, mult mai ușoare:
async function logTwoUsers( id1, id2 ) { const user1 = await wp.apiFetch( { url: '…' + id1 } ); const user2 = await wp.apiFetch( { url: '…' + id2 } ); console.log( user1, user2 ); } Ori de câte ori apelați o operație asincronă într-o funcție asincronă, puteți aștepta rezultatul acesteia folosind cuvântul cheie await . Singurul lucru de care ar trebui să rețineți este că, atunci când definiți o funcție async , rezultatul acesteia va fi întotdeauna o promisiune:
async function getNumberFive() { return 5; } const p = getNumberFive(); // a promise p.then( console.log ); // prints "5" # 4 Domeniu variabil atunci când se utilizează let și const
După cum probabil știți deja, acum puteți declara variabile folosind cuvintele cheie let și const . Primul definește o variabilă, iar cel de-al doilea definește o constantă:
let x = 1; console.log( x ); // 1 x = 2; console.log( x ); // 2 const y = 1; console.log( y ); // 1 y = 2; // Uncaught TypeError: invalid assignment to const 'y' console.log( y ); // 1 Ați putea fi tentat să credeți că let și var sunt același lucru, deoarece ambele cuvinte cheie ne permit să declarăm o variabilă neconstantă. Dar există o diferență substanțială între ele: domeniul lor. Cu let și const , domeniul de aplicare al variabilei este blocul în care este definită. În var , este întreaga funcție.
function fn() { if ( true ) { var x = 1; let y = 2; const z = 3; }//end if console.log( x ); // 1 console.log( y ); // Uncaught ReferenceError: y is not defined console.log( z ); // Uncaught ReferenceError: z is not defined } # 5 Transformarea datelor atunci când se utilizează JSON.parse
Funcția JSON.parse parsează un șir JSON și construiește un obiect JavaScript. De exemplu:
const x = JSON.parse( '{"x":1,"a":[1,2,3]}' ); // Object { x: 1, a: [ 1, 2, 3 ] } Ceea ce majoritatea oamenilor nu știu despre el este că susține un al doilea argument numit reviver . Acest parametru este o funcție care va fi executată pentru fiecare element care este analizat, permițându-vă să manipulați valoarea după cum doriți. De exemplu, imaginați-vă un șir JSON ca următorul:
const json = '{"name":"David","birthday":"1985-12-01T10:00:00.000Z"}'; Dacă folosim JSON.parse așa cum este, acesta va genera un obiect cu două atribute șir: name și ziua de birthday . Dar dacă oferim o funcție de JSON.parse reviver ne putem asigura că ziua de birthday este analizată ca Date :
const user = JSON.parse( json, ( key, value ) => 'birthday' === key ? new Date( value ) : value ) # 6 Separator numeric în codul sursă folosind caracterul subdesrcore ( _ )
Ultimul nostru sfat de astăzi este separatorul numeric. Există o propunere (în prezent în etapa 4) care face posibilă scrierea numerelor într-un mod care să fie mai ușor de înțeles de către oameni. De exemplu, poți să spui cu adevărat cât de mari sunt următoarele numere?
10000000000 2189719.25 Dacă am putea folosi separatorul de mii, ar fi mult mai ușor de interpretat! Și exact asta putem face folosind liniuța de subliniere _ :
10_000_000_000 2_189_719.25rezumat
Este posibil să scrieți un cod JavaScript mai bun dacă vă obișnuiți cu toate instrumentele și funcțiile noi incluse în JavaScript. Astăzi am văzut câteva exemple de ceea ce este posibil cu acest limbaj de programare. Sper că ai învățat ceva nou și dacă ți-a plăcut, nu uita să-l împărtășești cu colegii tăi. Ne vedem în curând!
Imagine prezentată de Sam Dan Truong pe Unsplash.
