.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!