Etienne Talbot

Sledovat

Jan 29, 2018 · 7 min číst

Pokud začínáte v Javascriptu, možná jste ještě neslyšeli o .map() .reduce() .filter()., Pro mě to chvíli trvalo, než jsem musel před několika lety podporovat Internet Explorer 8. Pokud však nemusíte být kompatibilní s tímto velmi starým prohlížečem, musíte se s těmito metodami seznámit.

Vezměte na vědomí, že tento článek se s největší pravděpodobností vztahuje i na jakékoliv jiné programovací jazyk používáte, jako jsou koncepty, které existují v mnoha jiných jazycích.

dovolte mi vysvětlit, jak to funguje s jednoduchým příkladem. Řekněme, že jste obdrželi pole obsahující více objektů – každý z nich představuje osobu., Věc, kterou opravdu potřebujete na konci, ačkoli, je pole obsahující pouze id každé osoby.

pojďme porovnat!

použití .forEach():

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

Všimněte si, jak musíte předem vytvořit prázdné pole? Pojďme se podívat, jak to vypadá, když pomocí .map():

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

dokonce můžeme být stručnější s šipkou funkce (vyžaduje ES6 podporu, Babel nebo psacím Stroji)

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

Tak jak to .map() práce?, V podstatě se přebírá 2 argumenty, zpětné volání a volitelně kontextu (budou považovány za this v callback), které jsem nepoužil v předchozím příkladu. Zpětné volání běží pro každou hodnotu v poli a vrací každou novou hodnotu ve výsledném poli.

mějte na paměti, že výsledné pole bude mít vždy stejnou délku jako původní pole.

.snížení()

Stejně jako .map() .reduce() také spustí zpětné volání pro každý prvek pole., Co je zde odlišné, je to, že reduce předává výsledek tohoto zpětného volání (akumulátoru) z jednoho prvku pole do druhého.

Akumulátor může být do značné míry cokoliv (celé číslo, řetězec, objekt atd.) a musí být při volání .reduce()instantován nebo předán.

čas na příklad! Řekněme, že máte pole s těmito piloty a jejich příslušné dlouholeté zkušenosti:

potřebujeme znát celkové dlouholeté zkušenosti všech z nich., .reduce(), je to docela jednoduché:

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

Všimněte si, že jsem nastavit výchozí hodnotu 0. V případě potřeby bych také mohl použít existující proměnnou. Po spuštění zpětného volání pro každý prvek pole, snížit vrátí poslední hodnotu našich akumulátor (v našem případě: 82).

podívejme se, jak to lze zkrátit pomocí funkcí ES6 arrow:

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

nyní řekněme, že chci zjistit, který pilot je nejzkušenější., K tomu mohu použít také redukci:

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

pojmenoval jsem svůj akumulátor oldest. Moje zpětné volání porovnává akumulátor s každým pilotem. Pokud má pilot více let zkušeností než oldest, pak se tento pilot stane novým oldest takže to je ten, který se vrátím.

jak můžete vidět, pomocí .reduce() je snadný způsob, jak vygenerovat jednu hodnotu nebo objekt z pole.

.filtr ()

Co když máte pole, ale chcete v něm pouze některé prvky?, To je místo, kde .filter() přichází!

zde jsou naše data:

Řekněme, že teď chceme dvě pole: jedno pro povstalecké piloty, druhé pro Imperiály. S .filter() to nemůže být jednodušší!

to je ono! A je to ještě kratší s funkcemi šipky:

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

v podstatě, pokud funkce zpětného volání vrátí true, aktuální prvek bude ve výsledném poli. Pokud se vrátí nepravdivé, nebude.

kombinace .mapa(), .snížit (), a .,filtr()

Protože všechny tři jsou tzv. na pole a jelikož .map() .filter() jak vrátit pole, můžeme snadno řetězec naše volání.

podívejme se na další příklad. Zde jsou naše data:

náš cíl: získejte pouze celkové skóre uživatelů síly. Pojďme to udělat krok za krokem!

nejprve musíme odfiltrovat personál, který nemůže použít sílu:

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

s tím máme ve výsledném poli 3 prvky. Nyní musíme vytvořit pole obsahující celkové skóre každého Jediho.,

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

A teď to pojďme použít, snížit dostat celkem:

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

A teď tady je ta zábavná část… můžeme řetězce toto všechno získat, co chceme v jednom řádku:

A podívejte se, jak pěkně je s šipkou funkce:

Bum! 💥

poznámka: v mém předchozím příkladu nebyly ani nutné .map() a .filter(). Stejného výsledku bychom mohli snadno dosáhnout pouze pomocí .reduce(). Nechal jsem je tam kvůli tomuto příkladu., Dokážete odhadnout, jak bychom mohli udržet .reduce() a získat stejný výsledek s jedním řádkem kódu? Viz řešení na CodePen

proč nepoužívat .forEach ()?

používal jsem for smyčky všude místo .map() .reduce() .filter(). Ale před pár lety jsem začal pracovat mnohem více s daty, která pocházejí z API. Tam jsem začal vidět výhody opuštění .forEach za sebou.,

formátování

říkají, že je třeba zobrazit seznam lidí s jejich jménem a názvem úlohy.

var data = 

API vám dává výše uvedená data, ale potřebujete pouze název a příjmení každé osoby… musíte data naformátovat. Vaše aplikace však musí mít také jeden pohled pro každou osobu, takže musíte napsat funkci formátování dat, která funguje jak v zobrazení seznamu, tak v jediném zobrazení.,

to znamená, Že nemůžete mít .forEach smyčka uvnitř vašeho formátování funkce, jinak budete muset zabalit jeden prvek v poli, než budete předat jej k funkci stačí, aby to fungovalo, tak jako:

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

Takže vaše smyčky musí zabalit volání funkce, jako je tento:

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

.forEach() nevrátí nic. To znamená, že musíte výsledky posunout do předem určeného pole.,

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

Jako výsledek, budete mít 2 funkce: formatElement() funkce a funkce, které tlačí na výsledky ve vašem pole.

proč máte 2 funkce, když můžete mít jen jednu?

var results = data.map(formatElement);

Testování je jednodušší

Pokud budete psát unit testy pro váš kód, zjistíte, že je jednodušší, aby se test funkce volání s .map() .reduce() nebo .filter().

vše, co musíte udělat, je poskytnout příchozí data pro funkci a očekávat, že výsledek vyjde., V podstatě “ co vyjde, pokud to projde?”. Méně manipulace, méně beforeEach()s a afterEach()s. Je to jednoduché, jednoduché testování.

zkuste to!

Pokud se vám líbil tento článek a chcete se dozvědět více array metody, podívejte se na můj článek o tom, jak používat .some() .find() v Javascriptu.

Udržujte kódování!

Articles

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *