Etienne Talbot

Follow

Jan 29, 2018 · 7 min de citit

Dacă începi în JavaScript, poate n-ai auzit de .map(), .reduce() și .filter()., Pentru mine, a durat ceva timp, deoarece a trebuit să susțin Internet Explorer 8 până acum câțiva ani. Dar dacă nu trebuie să fiți compatibil cu acest browser foarte vechi, trebuie să vă familiarizați cu aceste metode.rețineți că acest articol se aplică cel mai probabil oricărui alt limbaj de programare pe care îl utilizați, deoarece acestea sunt concepte care există în multe alte limbi.

permiteți-mi să explic cum funcționează cu un exemplu simplu. Spuneți că ați primit o matrice care conține mai multe obiecte – fiecare reprezentând o persoană., Lucru într-adevăr nevoie în cele din urmă, deși, este o matrice care conține doar id-ul fiecărei persoane.

să comparăm!

folosind .forEach():

var officersIds = ;officers.forEach(function (officer) {
officersIds.push(officer.id);
});

observați cum trebuie să creați o matrice goală în prealabil? Să vedem ce se pare ca atunci când se utilizează .map():

var officersIds = officers.map(function (officer) {
return officer.id
});

putem fi chiar mai concis cu săgeată funcții (necesită ES6 sprijin, Babel sau mașina de Scris)

const officersIds = officers.map(officer => officer.id);

Deci, cum face .map() lucru?, Practic este nevoie de 2 argumente, un apel invers și un context opțional (va fi considerat ca this în callback) pe care nu l-am folosit în exemplul anterior. Callback-ul rulează pentru fiecare valoare din matrice și returnează fiecare nouă valoare din matricea rezultată.rețineți că matricea rezultată va avea întotdeauna aceeași lungime ca matricea originală.

.reduce()

ca .map(), .reduce() conduce, de asemenea, un apel invers pentru fiecare element al unei matrice., Ceea ce este diferit aici este faptul că reduce trece rezultatul acestui apel invers (acumulatorul) de la un element de matrice la altul.

acumulatorul poate fi destul de mult orice (întreg, șir, obiect, etc.) și trebuie să fie instanțiat sau trecut atunci când apelați .reduce().

timp pentru un exemplu! Să presupunem că aveți o serie cu acești piloți și anii lor de experiență:

trebuie să cunoaștem totalul anilor de experiență ai tuturor., Cu .reduce(), e destul de simplu:

var totalYears = pilots.reduce(function (accumulator, pilot) {
return accumulator + pilot.years;
}, 0);

Observați că am stabilit începând cu valoarea 0. Aș fi putut folosi și o variabilă existentă dacă era necesar. După rularea apelului invers pentru fiecare element al matricei, reducerea va returna valoarea finală a acumulatorului nostru (în cazul nostru: 82).

Să vedem cum poate fi scurtat acest lucru cu funcțiile săgeată ale ES6:

const totalYears = pilots.reduce((acc, pilot) => acc + pilot.years, 0);

acum să spunem că vreau să aflu care pilot este cel mai experimentat., Pentru asta, pot folosi și reducerea:

var mostExpPilot = pilots.reduce(function (oldest, pilot) {
return (oldest.years || 0) > pilot.years ? oldest : pilot;
}, {});

am numit acumulatorul meu oldest. Apelul meu invers compară acumulatorul cu fiecare pilot. Dacă un pilot are mai multe de ani de experiență decât oldest, apoi ca pilot devine noul oldest așa că asta mi-aș reveni.

după cum puteți vedea, folosind .reduce() este o modalitate ușoară de a genera o singură valoare sau obiect dintr-o matrice.

.filter ()

Ce se întâmplă dacă aveți o matrice, dar doriți doar unele dintre elementele din ea?, Aici vine .filter()!

Iată datele noastre:

să spunem că vrem două tablouri acum: una pentru piloții rebeli, cealaltă pentru imperiali. Cu .filter() nu ar putea fi mai ușor!

asta este! Și e chiar mai scurt cu săgeata de funcții:

const rebels = pilots.filter(pilot => pilot.faction === "Rebels");
const empire = pilots.filter(pilot => pilot.faction === "Empire");

de Fapt, dacă funcția de apel invers returnează true, elementul curent va fi in array. Dacă se întoarce fals, nu va fi.

combinarea .scurt (),.reduce (), și .,filtru()

Deoarece toate trei sunt numite pe tablouri și de .map() și .filter() ambele reveni tablouri, putem cu ușurință lanț apelurile noastre.

să verificăm un alt exemplu. Iată datele noastre:

obiectivul nostru: obțineți scorul total numai pentru utilizatorii force. Să o facem pas cu pas!mai întâi, trebuie să filtrăm personalul care nu poate folosi forța:

var jediPersonnel = personnel.filter(function (person) {
return person.isForceUser;
});// Result: (Luke, Ezra and Caleb)

cu asta avem 3 elemente rămase în matricea noastră rezultată. Acum trebuie să creăm o matrice care să conțină scorul total al fiecărui Jedi.,

var jediScores = jediPersonnel.map(function (jedi) {
return jedi.pilotingScore + jedi.shootingScore;
});// Result:

Și să folosim reduce pentru a obține total:

var totalJediScore = jediScores.reduce(function (acc, score) {
return acc + score;
}, 0);// Result: 420

Și acum, aici e partea distractiva… putem lanț de toate de acest lucru pentru a obține ceea ce ne dorim într-o singură linie:

Și uite cât de frumoasă este cu săgeata de funcții:

Boom-ul! 💥

Notă: În exemplul anterior, .map() și .filter() nu erau chiar necesare. Am putea obține cu ușurință același rezultat doar cu .reduce(). Le-am lăsat acolo de dragul acestui exemplu., Puteți ghici cum am putea păstra doar .reduce() și obține același rezultat cu o singură linie de cod? Consultați soluția de pe CodePen

De ce să nu utilizați .forEach ()?

am folosit pentru a utiliza for bucle peste tot în loc de .map(), .reduce() și .filter(). Dar acum câțiva ani am început să lucrez mult mai mult cu date care provin dintr-un API. Acolo am început să văd avantajele de a lăsa .forEach în urmă.,

formatare

spuneți că trebuie să afișați o listă de persoane, cu numele și titlul postului.

var data = 

API-ul vă oferă datele de mai sus, dar aveți nevoie doar de titlul și prenumele fiecărei persoane… trebuie să formatați datele. Cu toate acestea, aplicația dvs. trebuie să aibă o singură vizualizare pentru fiecare persoană, deci trebuie să scrieți o funcție de formatare a datelor care funcționează atât într-o vizualizare listă, cât și într-o singură vizualizare.,

asta înseamnă Că nu poți avea .forEach în interiorul buclei de formatare funcție, sau altceva ce-ar fi să-și încheie singur element într-o matrice înainte de a trece la funcția doar de a face să funcționeze, astfel:

var result = formatElement();
// Yeah... that's not right at all

Deci bucla a pentru a încheia apelul funcției, astfel:

data.forEach(function (element) {
var formatted = formatElement(element);
// But what then....
});

.forEach() nu se întoarce nimic. Asta înseamnă că trebuie să împingi rezultatele într-o matrice predeterminată.,

var results = ;data.forEach(function (element) {
var formatted = formatElement(element);
results.push(formatted);
});

Ca rezultat, au 2 funcții: ta formatElement() funcția și funcția care împinge rezultate în matrice.de ce să ai 2 funcții când poți avea doar una?

var results = data.map(formatElement);

de Testare este mai ușor

Dacă ai scrie teste unitare pentru codul dvs., veți găsi că este mai simplu pentru a testa funcțiile pe care le numim cu .map(), .reduce() sau .filter().tot ce trebuie să faceți este să furnizați date de intrare pentru funcție și să așteptați să apară un rezultat., Practic „ce iese dacă acest lucru este trecut?”. Mai puțin de manipulare, mai puțin beforeEach()s și afterEach() – uri. E simplu, simplu de testare.

încearcă!

Dacă ți-a plăcut acest articol și doriți să aflați mai multe matrice metode, a verifica afară articolul meu despre cum să folosiți .some() și .find() în JavaScript.

păstrați codificarea!

Articles

Lasă un răspuns

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