Etienne Talbot

Følg

Jan 29, 2018 · 7 min lese

Hvis du starter i JavaScript, kanskje du ikke har hørt av .map(), .reduce(), og .filter()., For meg, det tok en stund så jeg måtte støtte for Internet Explorer 8 før et par år siden. Men hvis du ikke trenger å være kompatible med denne svært gammel nettleser, må du bli kjent med disse metodene.

Ta oppmerksom på at denne artikkelen mest sannsynlig gjelder uansett hva andre programmeringsspråk som du kan bruke, så dette er begreper som finnes i mange andre språk.

La meg forklare hvordan det fungerer med et enkelt eksempel. Si at du har mottatt en matrise som inneholder flere objekter – som hver og en representerer en person., Den tingen du virkelig trenger til slutt, skjønt, er en matrise som inneholder bare id-en for hver person.

La oss sammenligne!

ved Hjelp av .forEach():

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

legg Merke til hvordan du nødt til å opprette en tom matrise på forhånd? La oss se hvordan det ser ut når du bruker .map():

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

Vi kan være enda mer presis med pil funksjoner (krever ES6 støtte, Babel-eller maskinskrevet kopi)

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

Så hvordan gjør .map() arbeid?, I utgangspunktet er tar 2 argumenter, tilbakeringing og en valgfri sammenheng (vil bli betraktet som this i innb.) som jeg ikke bruker i forrige eksempel. Innb. går for hver verdi i matrise og returnerer hver ny verdi i den resulterende matrisen.

husk at den resulterende matrisen vil alltid være det samme lengde som den opprinnelige matrisen.

.redusere()

Akkurat som .map(), .reduce() driver også en tilbakeringing for hvert element i en matrise., Det som er annerledes her er at redusere passerer resultatet av denne tilbakeringing (akkumulatoren) fra en matrise elementet til den andre.

akkumulatoren kan være ganske mye annet (heltall, string, objekt, etc.), og må være startet eller bestått når du ringer .reduce().

Tid for et eksempel! Si at du har en tabell med disse pilotene og deres respektive års erfaring:

Vi trenger å vite den totale års erfaring i alle av dem., Med .reduce(), det er ganske enkelt:

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

legg Merke til at jeg har satt den starter verdi som 0. Jeg kunne også ha brukt en eksisterende variabel hvis det er nødvendig. Etter å ha kjørt innb. for hvert element i matrisen, reduserer du vil gå tilbake til den endelige verdien av våre akkumulator (i vårt tilfelle: 82).

La oss se hvordan dette kan bli forkortet med ES6 er pil funksjoner:

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

la oss Nå si at jeg ønsker å finne noe som pilot er den mest erfarne ett., For at jeg kan bruke redusere så vel:

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

jeg heter min akkumulator oldest. Min innb. sammenligner akkumulator til hver pilot. Hvis en pilot som har flere års erfaring enn oldest, deretter som pilot som blir den nye oldest så det er den jeg kommer tilbake.

Som du kan se, ved hjelp av .reduce() er en enkel måte å produsere en enkelt verdi, eller objekt fra en matrise.

.filteret()

Hva hvis du har en array, men vil bare noen av elementene i det?, Det er der .filter() kommer i!

Her er våre data:

Si at vi vil ha to matriser nå: en opprører piloter, den andre for imperials. Med .filter() det kan ikke bli enklere!

det er det! Og det er enda kortere med pil funksjoner:

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

i Utgangspunktet, hvis tilbakering funksjon returnerer sann, det aktuelle elementet vil være i den resulterende matrisen. Hvis den returnerer false, det vil ikke være.

Sammenslåing .kart(), .redusere(), og .,filteret()

Siden alle tre er kalt på matriser og siden .map() og .filter() begge returnerer matriser, kan vi lett kjede våre samtaler.

La oss sjekke ut et annet eksempel. Her er våre data:

Vårt mål: få det totale resultat av makt-brukere. La oss gjøre det, trinn for trinn!

for det Første, vi trenger å filtrere ut personell som ikke kan bruke the force:

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

Med at vi har 3 elementer venstre i vår resulterende matrisen. Vi trenger nå å opprette en matrise som inneholder totalt score i hver Kamp.,

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

Og la oss bruke redusere for å få total:

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

Og nå, her er den morsomme delen… vi kan kjede alt dette for å få det vi vil ha i en enkelt linje:

Og se så nydelig det er med pil funksjoner:

Boom! 💥

Merk: I mitt forrige eksempel, .map() og .filter() var ikke engang nødvendig. Vi kan lett oppnå samme resultat med bare .reduce(). Jeg forlot dem i det for å få til dette eksemplet., Kan du gjette hvor vi kunne bare holde .reduce() og få det samme resultatet med én linje med kode? Se løsningen på CodePen

Hvorfor ikke bruke .forEach()?

jeg pleide å bruke for loops overalt i stedet for .map(), .reduce(), og .filter(). Men for et par år siden jeg begynte å jobbe mye mer med data som kom fra et API. Det er der jeg begynte å se fordelene av å forlate .forEach bak.,

Formatering

Si at du trenger å vise en liste over mennesker, med sine navn og stillingstittel.

var data = 

API gir deg de ovennevnte data, men du trenger bare tittelen, og det siste navnet på hver person… Du må formatere data. Men appen har også behov for å ha en enkelt visning for hver person, så du må skrive inn en data formatering funksjonen som både fungerer i en liste vis og i en enkelt visning.,

Som betyr at du ikke kan ha .forEach loop innsiden av formatering funksjonen, eller ellers du ville ha til å vikle ett element i en matrise før du sender den til funksjonen bare for å gjøre det arbeidet, for eksempel slik:

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

Slik at løkken har for å bryte samtalen av funksjon, slik som dette:

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

, Men .forEach() ikke returnere noe. Det kan den ikke. Det betyr at du har å presse resultater inne en forhåndsbestemt utvalg.,

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

Som et resultat, du har 2 funksjoner: din formatElement() funksjon og funksjon som presser resultatene i gruppen.

Hvorfor har 2 funksjoner når du kan ha bare ett?

var results = data.map(formatElement);

– Testing er enklere

Hvis du skriver unit tester for koden din, du vil finne det enklere å teste funksjonene du ringer med .map(), .reduce(), eller .filter().

Alt du trenger å gjøre er å gi inngående data for funksjon og forventer et resultat for å komme ut., I utgangspunktet «hva som kommer ut av om dette er gått?». Mindre manipulasjon, mindre beforeEach()s og afterEach()s. Det er grei, enkel testing.

Prøv det!

Hvis du likte denne artikkelen, og ønsker å lære mer array metoder, sjekk ut min artikkel om hvordan du kan bruke .some() og .find() i JavaScript.

Hold koding!

Articles

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *