Uwaga! Trwają prace nad nową wersją serwisu. Mogą występować przejściowe problemy z jego funkcjonowaniem. Przepraszam za niedogodności!
⛔ Potrzebujesz wsparcia? Oceny CV? A może Code Review? ✅ Dołącz do naszej społeczności na Discordzie!
Framework czy biblioteka JS jak React to kolejny krok podczas nauki programowania. Warto zrobić go, mając usystematyzowane podstawy. Zobacz, jakich metod JavaScript często używa się podczas pracy z Reactem (choć nie tylko) i jak pomagają one w operowaniu na danych. W artykule znajdziesz wyjaśnienie działania pięciu popularnych metod tablicowych oraz przykłady ich zastosowania.
Chcesz lepiej zapamiętać to zagadnienie? Wykonaj warsztat z JavaScript: Podstawy, aby osiągnąć swój cel!
Metoda map() w JavaScript służy do iteracji po elementach tablicy i przekształcania ich w nowe elementy na podstawie określonej funkcji (callbacku). Funkcję tę przekazujemy do metody jako argument.
Tak utworzone elementy trafiają do nowej tablicy, którą metoda map() zwraca.
Metoda map() przechodzi przez każdy element tablicy i wykonuje na nim operacje określone w callbacku, przekształcając go w nowy element.
Warto pamiętać, że callback może korzystać nie tylko z elementów tablicy, ale też z ich numerów indeksów oraz samej przetwarzanej tablicy:
const numbers = [1, 2, 3, 4, 5]; const multipliedNumbers = numbers.map((element, index, array) => { // Jeśli tablica ma więcej elementów niż jeden, to… if (array.length > 1) { // elementy z indeksami parzystymi pomnóż razy 2, a pozostałe razy 3 return index % 2 === 0 ? element * 2 : element * 3 } return element // gdyby tablica miała jeden element lub mniej, zwróć tylko ten element }); console.log(multipliedNumbers) // [2, 6, 6, 12, 10]
To bardzo teoretyczny przykład, lecz zwłaszcza wykorzystanie indeksu może Ci się niejednokrotnie przydać. Zwróć jednak uwagę, że nawiązanie do tablicy poprzez argument array (nazwa jest dowolna) też przynosi korzyści. Gdyby nazwa tablicy numbers uległa zmianie, a użylibyśmy jej wcześniej w ciele callbacku, wówczas trzeba by ją zmieniać w co najmniej dwóch miejscach.
Metoda map() zwraca nową tablicę, w której każdy element jest wynikiem przekształcenia odpowiadającego mu elementu z oryginalnej tablicy.
Metoda map() jest wykorzystywana w Reakcie niemal na każdym kroku do tworzenia podobnych komponentów różniących się zawartością, np. jak kafelki prezentujące produkty w sklepie internetowym czy lista znajomych na Facebooku (każdy element wygląda podobnie, lecz różni się zawartością). Poniżej widzisz bardzo prosty komponent funkcyjny, który zawiera listę e-booków.
const ProductList = () => { const productTitles = ['Ebook1', 'Ebook2', 'Ebook3']; // Tworzymy tablicę z elementami <li> const productItems = productTitles.map((title, index) => ( <li key={index}>{title}</li> )) // Wyświetlamy listę produktów return ( <ul> {productItems} </ul> ); }; // Powyższy kod po kompilacji do JS wygląda tak: <ul> <li>Ebook1</li> <li>Ebook2</li> <li>Ebook3</li> </ul>
Tytuły książek zamieszczone są w tablicy productTitles. Na jej podstawie tworzymy elementy li przechowywane w zmiennej productItems. Zmienną tę umieszczamy wewnątrz ul i w ten sposób uzyskujemy listę e-booków (nie przejmuj się, jeśli nie rozumiesz jeszcze składni Reacta).
Metoda forEach() działa niemal tak samo jak metoda map(), dlatego nie będziemy jej szczegółowo omawiać. Dodatkowo do tworzenia czy edytowania komponentów jest wykorzystywana raczej rzadko.
forEach() iteruje po elementach tablicy i wykonuje na nich operacje określone w przekazanym callbacku, ale nic nie zwraca (a dokładniej zwraca undefined). W Reakcie użyjesz jej jak w zwykłym JS-ie – np. do walidacji wartości z formularza.
W callbacku metody forEach() również mamy dostępne trzy parametry: element, numer indeksu i tablicę, po której iterujemy.
Wyżej wspomniany został przykład walidacji formularza JS. Dane o polach przechowujemy w tablicy formFields i to na jej podstawie generujemy formularz. Sprawdzenie, czy pola zostały wypełnione, mogłoby wyglądać tak:
const fields = [{ name: 'firstName', label: 'Imię', required: true }, { name: 'lastName', label: 'Nazwisko', required: true }, { name: 'city', label: 'Miasto', required: true } ]; // (...) – kod odpowiedzialny za generowanie pól formularza w drzewie DOM const formEl = document.querySelector('form'); // walidacja – sprawdzamy, czy każde z pól zostało wypełnione fields.forEach(function(field) { // wykorzystujemy właściwość obiektu o nazwie name, by pobrać wartość konkretnego elementu formularza const value = formEl.elements[field.name].value; if (field.required) { if (value.length === 0) { errors.push('Dane w polu ' + field.label + ' są wymagane.'); } } })
Metoda filter() w JavaScript służy do filtrowania elementów tablicy na podstawie określonego warunku. Przyjmuje ona funkcję zwrotną (callback), która decyduje, czy dany element spełnia warunek filtrowania.
Metoda filter() przechodzi przez każdy element tablicy. Jeśli element ten spełnia warunek podany w callbacku (true), to zostaje on dodany do nowej tablicy. Jeśli nie spełnia warunku (false), zostaje odrzucony.
Tak, tutaj callback również może korzystać nie tylko z elementów tablicy, ale i z ich numerów indeksów oraz samej przetwarzanej tablicy.
Metoda filter() zwraca nową tablicę. Zawiera ona tylko te elementy, które spełniły warunek filtrowania w callbacku.
W Reakcie komponenty możemy wyświetlać zależnie od akcji użytkownika. Dla przykładu udostępnimy w sklepie filtry do pokazania jedynie produktów z danego przedziału cenowego Zaimplementujemy to właśnie za pomocą metody filter().
// Przykładowa tablica produktów z serwera const products = [ { id: 1, name: 'Product 1', price: 10 }, { id: 2, name: 'Product 2', price: 20 }, { id: 3, name: 'Product 3', price: 15 }, { id: 4, name: 'Product 4', price: 25 }, ]; // Przykład filtrowania produktów. Uproszczony (zauważ, że ceny są wpisane ręcznie, a nie pobrane od użytkownika) const filteredByPrice = products.filter((product) => { return product.price >= 10 && product.price <= 20; });
Dzięki metodzie filter() uzyskaliśmy nową tablicę w zmiennej filteredByPrice. Zawiera ona trzy pierwsze produkty, ponieważ tylko one spełniają warunek filtrowania (zakres ceny od 10 do 20).
W Reakcie na jej podstawie dzięki użyciu metody map() wyrenderowalibyśmy odpowiednie komponenty. Po stronie interfejsu użytkownika wyglądałoby to w ten sposób, że po zatwierdzeniu wartości filtra cenowego, wyświetliłyby się produkty numer 1, 2 i 3.
Metoda find() w JavaScript służy do wyszukiwania w tablicy pierwszego elementu, który spełnia określony warunek. Przyjmuje ona funkcję zwrotną (callback), która decyduje, czy dany element spełnia warunek wyszukiwania.
Metoda find() przechodzi przez każdy element tablicy. Jeśli element ten spełnia warunek podany w callbacku (true), to zostaje on zwrócony. Jeśli żaden element nie spełnia warunku (false), metoda zwraca undefined.
Uwaga: Wartość falsy (czyli np. właśnie undefined) będzie w Reakcie przydatna przy tzw. renderowaniu warunkowym – spójrz na przykład poniżej.
const products = [ { id: 1, name: 'Product 1', price: 10 }, { id: 2, name: 'Product 2', price: 20 }, { id: 3, name: 'Product 3', price: 15 }, { id: 4, name: 'Product 4', price: 25 }, ]; const ProductComponent = () => { const product = products.find((prod) => prod.id === 2); // szukamy produktu o ID równym 2 // Jeśli metoda find() zwróci wyszukany element, to zostanie on wyrenderowany; jeśli zwróci undefined, to wyświetli się komunikat return ( <p>{product ? product.name : 'Product not found'}</p> ); };
Trzy parametry w callbacku – element, numer indeksu i tablica
Tutaj jak wcześniej: callback może korzystać nie tylko z elementów tablicy, ale i z ich numerów indeksów oraz samej przetwarzanej tablicy.
Metoda find() zwraca albo znaleziony element, albo undefined, jeśli nie znajduje żadnego elementu spełniającego warunek.
Używaj find() zawsze tam, gdzie spodziewasz się znalezienia jednego elementu (w przeciwnym razie stosuj metodę filter()).
Poniżej widzisz przykład formularza HTML. Załóżmy, że chcemy sprawdzić poprawność wprowadzonych przez użytkownika danych w polu kodu pocztowego. Pole to ma nadaną przez nas niepowtarzalną nazwę "zip", dzięki czemu możemy wyszukać je metodą find() i sprawdzić, czy wprowadzona wartość pasuje do wyrażenia regularnego.
<form action="" method="post" novalidate> <ul class="messages"></ul> <div> <label> Imię <input name="firstName" required /> </label> </div> <div> <label> Nazwisko <input name="lastName" required /> </label> </div> <div> <label> Kod pocztowy <input name="zip" pattern="^[0-9]{2}-[0-9]{3}$" required /> </label> </div> <div><button type="submit">Wyślij</button></div> </form>
// Wyszukujemy formularz const form = document.querySelector("form"); // Uzyskujemy tablicę z elementami formularza const fields = Array.from(form.elements); form.addEventListener("submit", e => { e.preventDefault(); // Wyszukujemy element o nazwie "zip" const zipField = fields.find(field => field.name === "zip"); // Jeśli pole z kodem pocztowym nie jest zgodne ze wzorem (regexem), to wyświetlamy komunikat o błędzie if (!/^[0-9]{2}-[0-9]{3}$/.test(zipField.value)) { alert("Nieprawidłowy kod pocztowy") } })
Metoda reduce() służy do iteracji po elementach tablicy i agregacji ich wartości w celu uzyskania pojedynczego wyniku. Może być używana m.in. do sumowania czy obliczania średniej.
Metoda ta przechodzi przez każdy element tablicy i wykonuje na nim określone przez nas w callbacku operacje. Dodatkowo akumuluje przekazane wartości w jedną końcową wartość. O tym, jakim typem danych ma być wartość końcowa (liczbą, obiektem, tablicą itd.), decydujemy sami.
Funkcja przekazywana do reduce() przyjmuje dwa argumenty: akumulator i aktualny element tablicy.
const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
W ciele funkcji określamy, jakie operacje należy wykonać na obecnych wartościach, i jak zaktualizować wartość akumulatora.
Jako drugi argument po funkcji redukującej (callbacku) możemy przekazać początkową wartość akumulatora (w przykładzie poniżej to 0). Określa ona, czym powinien być akumulator przed rozpoczęciem iteracji.
const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
Tworzysz sklep, w którym produkty jako obiekty trafiają do koszyka. Aby podsumować kwotę do zapłaty, możesz skorzystać właśnie z reduce():
const cartItems = [ { id: 1, name: 'Product 1', price: 10 }, { id: 2, name: 'Product 2', price: 20 }, { id: 3, name: 'Product 3', price: 15 }, ]; const totalPrice = cartItems.reduce((sum, item) => sum + item.price, 0); console.log(totalPrice); // 45
Ale uwaga! Wartością końcową, jak wspomnieliśmy, wcale nie musi być liczba. Może to być obiekt, w którym zgromadzimy pogrupowane dane. Zobacz, jak grupować dane za pomocą metody reduce().
Przed rozpoczęciem nauki Reacta (albo Vue, Angulara itp.) warto przypomnieć sobie jeszcze, jak działa destrukturyzacja oraz czym jest rozproszenie i parametr reszty.
Przyda Ci się również przypomnienie działania metody sort(), którą omawiam w osobnym artykule.
Udostępnij ten artykuł:
Potrzebujesz cotygodniowej dawki motywacji?
Zapisz się i zgarnij za darmo e-book o wartości 39 zł!
PS. Zazwyczaj rozsyłam 1-2 wiadomości na tydzień. Nikomu nie będę udostępniał Twojego adresu email.
Mam coś dla Ciebie!
W każdy piątek rozsyłam motywujący do nauki programowania newsletter!
Dodatkowo od razu otrzymasz ode mnie e-book o wartości 39 zł. To ponad 40 stron konkretów o nauce programowania i pracy w IT.
PS Zazwyczaj wysyłam 1-2 wiadomości na tydzień. Nikomu nie będę udostępniał Twojego adresu e-mail.