Etienne Talbot

Følg

Jan 29, 2018 · 7 min læse

Hvis du begynder i JavaScript, måske har du ikke hørt om .map() .reduce() og .filter()., For mig tog det et stykke tid, da jeg var nødt til at støtte Internet e .plorer 8 indtil for et par år siden. Men hvis du ikke behøver at være kompatibel med denne meget gamle bro .ser, skal du blive fortrolig med disse metoder.

Vær opmærksom på, at denne artikel sandsynligvis gælder for det andet programmeringssprog, du muligvis bruger, da dette er begreber, der findes på mange andre sprog.

Lad mig forklare, hvordan det fungerer med et simpelt eksempel. Sig, at du har modtaget et array, der indeholder flere objekter – hver repræsenterer en person., Det, du virkelig har brug for i sidste ende, er dog et array, der kun indeholder id for hver person.

lad os sammenligne!

brug .forEach():

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

bemærk, hvordan du skal oprette et tomt array på forhånd? Lad os se, hvad det ligner, når du bruger .map():

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

Vi kan endda være mere præcise med pil funktioner (kræver ES6 støtte, Babel eller Skrivemaskine)

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

Så hvordan gør .map() arbejde?, Dybest set tager 2 argumenter, en tilbagekald og en valgfri kontekst (vil blive betragtet som this i tilbagekald), som jeg ikke brugte i det foregående eksempel. Tilbagekald kører for hver værdi i arrayet og returnerer hver ny værdi i det resulterende array.

Husk, at det resulterende array altid vil være den samme længde som det originale array.

.reducer()

ligesom .map() .reduce() kører også en tilbagekaldsanmodning for hvert element i et array., Hvad er anderledes her er, at reducere passerer resultatet af denne tilbagekald (akkumulatoren) fra et array element til den anden.

akkumulatoren kan være stort set alt (heltal, streng, objekt osv.) og skal være instantieret eller bestået, når du ringer .reduce().

tid til et eksempel! Sig, at du har et array med disse piloter og deres respektive års erfaring:

Vi er nødt til at kende de samlede års erfaring med dem alle., Med .reduce() er det ret ligetil:

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

Bemærk, at jeg har indstillet startværdien som 0. Jeg kunne også have brugt en eksisterende variabel om nødvendigt. Efter at have kørt tilbagekald for hvert element i arrayet, vil reduce returnere den endelige værdi af vores akkumulator(i vores tilfælde: 82).

lad os se, hvordan dette kan forkortes med ES6S pilefunktioner:

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

lad os nu sige, at jeg vil finde ud af, hvilken pilot der er den mest erfarne., Til det kan jeg også bruge reducer:

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

Jeg hedder Min akkumulator oldest. Min tilbagekald sammenligner akkumulatoren med hver pilot. Hvis en pilot har flere års erfaring end oldest, bliver denne pilot den nye oldest så det er den, jeg vender tilbage.

Som du kan se, ved hjælp af .reduce() er en nem måde at generere en enkelt værdi eller en genstand fra et array.

.filter ()

Hvad hvis du har et array, men kun vil have nogle af elementerne i det?, Det er her .filter() kommer ind!

Her er vores data:

sig, at vi vil have to arrays nu: en til rebelpiloter, den anden til imperials. Med .filter() kunne det ikke være nemmere!

det er det! Og det er endnu kortere med pilefunktioner:

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

grundlæggende, hvis tilbagekaldsfunktionen returnerer true, vil det aktuelle element være i det resulterende array. Hvis det returnerer FALSK, vil det ikke være.

kombination .kortlægge(), .reducere (), og .,filter()

Da alle tre kaldes arrays, og da .map() og .filter() begge returnere arrays, kan vi let kæde på vores opkald.

lad os tjekke et andet eksempel. Her er vores data:

vores mål: få kun den samlede score for force-brugere. Lad os gøre det trin for trin!

først skal vi filtrere det personale, der ikke kan bruge kraften:

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

med det har vi 3 elementer tilbage i vores resulterende array. Vi skal nu oprette et array, der indeholder den samlede score for hver Jedi.,

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

Og lad os bruge reducer at få samlet:

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

Og her er nu den sjove del… vi kan kæde alt dette for at få, hvad vi ønsker i en enkelt linje:

Og se, hvor stort det er med pil funktioner:

Boom! Note

Bemærk: i mit tidligere eksempel var .map() og .filter() ikke engang nødvendigt. Vi kunne nemt opnå det samme resultat med kun .reduce(). Jeg efterlod dem derinde af hensyn til dette eksempel., Kan du gætte, hvordan vi kun kunne holde .reduce() og få det samme resultat med en kodelinje? Se løsningen på CodePen

hvorfor ikke bruge .forEach ()?

jeg plejede at bruge for sløjfer overalt i stedet for .map() .reduce() og .filter(). Men for et par år siden begyndte jeg at arbejde meget mere med data, der kom fra en API. Det var her jeg begyndte at se fordelene ved at forlade .forEach bag.,

formatering

sig, at du skal vise en liste over personer med deres navn og jobtitel.

var data = 

API ‘ en giver dig ovenstående data, men du behøver kun titlen og efternavnet på hver person… du skal formatere dataene. Din app skal dog også have en enkelt visning for hver person, så du skal skrive en dataformateringsfunktion, der begge fungerer i en listevisning og i en enkelt visning.,

det betyder, At du ikke kan have den .forEach loop inde i din formatering funktion, eller andet, du ville have til at pakke dit enkelt element i et array, før du giver det til den funktion, bare for at gøre det arbejde, som så:

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

Så din loop har til wrap kald af funktionen, som denne:

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

Men .forEach() ikke returnere noget. Det betyder, at du skal skubbe resultaterne ind i et forudbestemt array.,

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

Som et resultat, du har 2 funktioner: din formatElement() funktion og din funktion, der skubber resultater i dit array.

hvorfor har 2 funktioner, når du kun kan have en?

var results = data.map(formatElement);

Test er nemmere

Hvis du skriver unit tests for din kode, kan du finde det enklere at teste de funktioner, du kalder med .map() .reduce(), eller .filter().

alt hvad du skal gøre er at give indgående data for funktionen og forvente, at et resultat kommer ud., Dybest set ” hvad kommer ud, hvis dette er bestået?”. Mindre manipulation, mindre beforeEach()s afterEach()s. Det er ligetil, enkel test.

prøv det!

Hvis du kunne lide denne artikel og ønsker at lære mere array metoder, så tjek min artikel om, hvordan man bruger .some() og .find() i JavaScript.

Fortsæt kodning!

Articles

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *