Etienne Talbot

Follow
29 stycznia 2018 · 7 min czytać
p > Jeśli zaczynasz z JavaScript, być może nie słyszeli o .map() .reduce() i .filter()., Dla mnie zajęło to trochę czasu, ponieważ musiałem obsługiwać Internet Explorer 8 jeszcze kilka lat temu. Ale jeśli nie musisz być kompatybilny z tą bardzo starą przeglądarką, musisz zapoznać się z tymi metodami.

zwróć uwagę, że ten artykuł najprawdopodobniej odnosi się do dowolnego innego języka programowania, którego możesz używać, ponieważ są to pojęcia, które istnieją w wielu innych językach.

pozwól mi wyjaśnić, jak to działa na prostym przykładzie. Powiedzmy, że otrzymałeś tablicę zawierającą wiele obiektów-każdy z nich reprezentuje osobę., Rzecz, której naprawdę potrzebujesz w końcu, to tablica zawierająca tylko id każdej osoby.

porównajmy!

używając.forEach():

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

zauważ, jak musisz wcześniej utworzyć pustą tablicę? Zobaczmy, jak to wygląda, gdy używasz .map():

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

możemy być nawet bardziej zwięzli z funkcjami strzałek (wymaga obsługi ES6, Babel lub maszynopisu)

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

więc jak to działa .map() praca?, Zasadniczo trwa 2 argumenty, wywołanie zwrotne i opcjonalny kontekst (będą traktowane jako this w wywołaniu zwrotnym), których nie używałem w poprzednim przykładzie. Wywołanie zwrotne jest uruchamiane dla każdej wartości w tablicy i zwraca każdą nową wartość w tablicy wynikowej.

należy pamiętać, że tablica wynikowa będzie zawsze tej samej długości co tablica oryginalna.

.reduce()

podobnie jak .map(), .reduce() również uruchamia wywołanie zwrotne dla każdego elementu tablicy., Różnica polega na tym, że reduce przekazuje wynik tego wywołania zwrotnego (akumulatora) z jednego elementu tablicy do drugiego.

akumulatorem może być praktycznie wszystko (integer, string, object, itp.) i musi być utworzona lub przekazana podczas wywołania .reduce().

Czas na przykład! Powiedzmy, że masz szereg z tymi pilotami i ich odpowiednimi latami doświadczenia:

musimy znać łączną liczbę lat doświadczenia wszystkich z nich., Z .reduce() jest to dość proste:

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

zauważ, że ustawiłem wartość początkową jako 0. W razie potrzeby mogłem również użyć istniejącej zmiennej. Po uruchomieniu wywołania zwrotnego dla każdego elementu tablicy, reduce zwróci końcową wartość naszego akumulatora (w naszym przypadku: 82).

zobaczmy, jak można to skrócić za pomocą funkcji strzałek ES6:

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

teraz powiedzmy, że chcę znaleźć, który pilot jest najbardziej doświadczonym., W tym celu mogę również użyć reduce:

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

nazwałem mój akumulator oldest. Moje połączenie zwrotne porównuje akumulator do każdego pilota. Jeśli pilot ma więcej lat doświadczenia niż oldest, wtedy ten pilot staje się nowym oldest więc to ten, który wracam.

jak widać, użycie.reduce() jest łatwym sposobem na wygenerowanie pojedynczej wartości lub obiektu z tablicy.

.filter()

Co zrobić, jeśli masz tablicę, ale chcesz mieć w niej tylko niektóre elementy?, To tutaj .filter() wchodzi!

oto nasze dane:

powiedzmy, że chcemy teraz dwie tablice: jedną dla pilotów rebeliantów, drugą dla imperialistów. Z .filter() nie może być łatwiej!

To jest to! I jest jeszcze krótszy z funkcjami strzałek:

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

zasadniczo, jeśli funkcja zwrotna zwraca true, bieżący element będzie w wynikowej tablicy. Jeśli zwróci false, nie będzie.

Mapa (),reduce (), oraz .,filter()

ponieważ wszystkie trzy są wywoływane na tablicach i od .map() I .filter() obie zwracają tablice, możemy łatwo łączyć nasze wywołania.

sprawdźmy inny przykład. Oto nasze dane:

Nasz Cel: uzyskać całkowity wynik tylko dla użytkowników force. Zróbmy to krok po kroku!

najpierw musimy odfiltrować personel, który nie może użyć siły:

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

dzięki temu mamy 3 elementy w naszej tablicy wynikowej. Teraz musimy stworzyć tablicę zawierającą całkowity wynik każdego Jedi.,

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

i użyjmy reduce, aby uzyskać sumę:

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

a teraz zabawna część… możemy połączyć to wszystko, aby uzyskać to, co chcemy w jednej linii:

i zobaczyć, jak ładnie jest z funkcjami strzałek:

Boom! 💥

Uwaga: w moim poprzednim przykładzie .map()I.filter() nie były nawet konieczne. Możemy łatwo osiągnąć ten sam wynik tylko .reduce(). Zostawiłem je tam dla tego przykładu., Możesz zgadnąć, jak możemy zachować tylko .reduce() I uzyskać ten sam wynik z jednej linii kodu? Zobacz Rozwiązanie Na CodePen

dlaczego nie używać .forEach()?

używałemfor pętli Wszędzie zamiast.map(),.reduce() I.filter(). Ale kilka lat temu zacząłem pracować o wiele więcej z danymi pochodzącymi z API. To właśnie tam zacząłem dostrzegać zalety pozostawienia .forEach za sobą.,

formatowanie

powiedz, że musisz wyświetlić listę osób, z ich imieniem i tytułem pracy.

var data = 

API daje powyższe dane, ale potrzebujesz tylko tytuł i nazwisko każdej osoby… musisz sformatować dane. Jednak aplikacja musi również mieć pojedynczy widok dla każdej osoby, więc musisz napisać funkcję formatowania danych, która działa zarówno w widoku listy, jak i w jednym widoku.,

oznacza to, że nie możesz mieć pętli .forEach wewnątrz funkcji formatowania, w przeciwnym razie będziesz musiał zawinąć pojedynczy element w tablicę, zanim przekażesz go do funkcji, aby działał, tak:

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

więc twoja pętla musi zawinąć wywołanie funkcji, tak:

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

ale .forEach() nic nie zwraca. To oznacza, że musisz wrzucić wyniki do z góry określonej tablicy.,

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

w rezultacie masz 2 funkcje: swoją funkcjęformatElement() I funkcję, która wypycha wyniki w tablicy.

Po co mieć 2 funkcje skoro można mieć tylko jedną?

var results = data.map(formatElement);

testowanie jest łatwiejsze

jeśli napiszesz testy jednostkowe dla swojego kodu, łatwiej będzie przetestować funkcje wywołane przez .map(), .reduce() lub .filter().

wszystko, co musisz zrobić, to podać dane wejściowe dla funkcji i oczekiwać, że wynik wyjdzie., Zasadniczo „co wyjdzie, jeśli to przejdzie?”. Mniej manipulacji, mniej beforeEach()s I afterEach() s. to proste, proste testowanie.

spróbuj!

Jeśli spodobał ci się ten artykuł i chcesz dowiedzieć się więcej o metodach array, zapoznaj się z moim artykułem o tym, jak używać.some()I.find() w JavaScript.

koduj dalej!

Articles

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *