Diversity w polskim IT
Zeng Hou Lim
Zeng Hou LimFull Stack Software Engineer @ Lean Data, Inc.

Czym warto zastąpić pętlę for w JavaScript

Sprawdź, czym czasem warto zastąpić kolejną pętlę for, której zamierzasz użyć w JavaScript.
1.12.20205 min
Czym warto zastąpić pętlę for w JavaScript

Początkujący programiści najczęściej chcą budować rzeczy od zera oraz mieć większą kontrolę nad swoim kodem. Pracując z tablicami i obiektami w JavaScript, niektórzy z nas mogą preferować użycie for loop do iteracji po elementach lub kluczach podczas wykonywania pewnej logiki. Robienie tego nie jest błędem - w końcu pętle były jednymi z pierwszych koncepcji, których nauczyliśmy się podczas zajęć z informatyki. Ważne jest jednak, aby pamiętać o wbudowanych funkcjach wyższego rzędu w JS, które sprawią, że nasz kod będzie o wiele bardziej elegancki, czytelny i DRY. 

Czym jest funkcja wyższego rzędu?

Oto definicja:

Funkcja wyższego rzędu przyjmuje inną funkcję jako argument lub ją zwraca.


W tym artykule omówię siedem funkcji wyższego rzędu w JS, których ja najczęściej używam. W każdej sekcji spróbuję wyjaśnić, kiedy i jak należy każdej z nich używać.

1. forEach()

Metoda forEach() przyjmuje funkcję i wykonuje ją dla każdego elementu tablicy.


Kiedy używać?

forEach() ma raczej ogólne przeznaczenie, więc może być używane w wielu sytuacjach, również w tych, które realizują inne funkcje wyższego rzędu. Warto jednak pamiętać, że jeśli istnieje funkcja, która ma bardziej konkretne przeznaczenie, to zdecydowanie powinniśmy jej użyć, jeśli akurat możemy.

Inne funkcje omówimy szczegółowo później.


Składnia

arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);


Na najbardziej podstawowym poziomie funkcja, która jest przekazywana do forEach, musi przyjmować currentValue, pod którym znajdą się kolejne elementy z iteracji. W poniższym przykładzie nazywa się to elem. Pozostałe parametry opcjonalne są rozdzielone nawiasami kwadratowymi.


Przykład

const array = ['a', 'b', 'c'];
array.forEach(function(elem) {
    // using template literals here
    console.log(`Printing ${elem}`); 
});
// Printing a
// Printing b
// Printing c


Aby pokazać, jak możemy używać parametrów opcjonalnych, spójrzmy na poniższy przykład:

const array = ['a', 'b', 'c'];
array.forEach(function(elem, index, array) {
    console.log(`${elem} is at position ${index} of [${array}]`);
});
// a is at position 0 of the array [a, b, c]


Możemy też przekazać wartość this, która zostanie użyta jako wartość this w funkcji zwrotnej:

const array = ['a', 'b', 'c'];
array.forEach(function(elem, index, array) {
    console.log(array == this); // checking for pointer equality
}, array); // pass in `this` as optional param
// true

2. reduce()


Kiedy używać?

reduce() to niezwykle pomocna metoda, której można użyć do wydobycia pojedynczej wartości z tablicy przez wykonanie funkcji redukującej. Może się to wydawać nieco skomplikowane, ale chodzi tutaj o to, aby bieżącą wartość połączyć z poprzednią wartością zapisaną w rejestrze, uzyskując na koniec jedną wartość.

Poniższy przykład powinien wyjaśnić to trochę lepiej.

Mamy tutaj obiekt, który przechowuje wyniki egzaminu według sekcji, a my chcemy zobaczyć, jaki jest łączny wynik. reduce() świetnie się tutaj sprawdzi, bo chcemy mieć tylko jedną wartość.


Składnia

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])


Przykład

const scoresBySection = {
    math: 60,
    reading: 70,
    writing: 87,
};
const sectionNames = Object.keys(scoresBySection); // get array
const marks = sectionNames.reduce(function(accumulator, sectionName) {
    // the return value will be the accumulator for next iteration
    return accumulator + scoresBySection[sectionName];
}, 0) // initial value
console.log(marks) // 217


W moim poprzednim artykule pisałem o tym, jak używać funkcji reduce(), aby bezpiecznie uzyskać dostęp do wartości w obiekcie.

3. map()


Kiedy używać?

Gdybyśmy kiedykolwiek musieli zmodyfikować tablicę, to nadal moglibyśmy użyć funkcji forEach().


Składnia

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])


Przykład

const array = [1, 2, 3];
array.forEach(function(elem, index, array) {
    array[index] = elem * 2;
});
console.log(array); // [2,4,6]


Mówiliśmy jednak o tym, że jeśli mamy coś bardziej konkretnego niż forEach(), to powinniśmy tego użyć. Jeśli chcemy zrobić dokładną transformację istniejącej tablicy, to powinniśmy użyć map(). Przekazana funkcja jest wykonywana na każdej bieżącej wartości, a nowa tablica jest wtedy zwracana.

let array = [1,2,3];
array = array.map(function(elem) {
    return elem * 2;
});
console.log(newArray); // [2,4,6]


Warto zapamiętać, że używamy deklaratora let zamiast const, ponieważ z map() otrzymujemy nową tablicę. Musimy zatem ponownie przypisać nową wartość do tablicy zmiennych.

4. filter()


Kiedy używać?

Nie zawsze chcemy, aby wszystkie wartości znajdowały się w tablicy. Czasami chcemy tylko tych, które spełniają określone warunki. Możemy więc je odfiltrować z podzbioru oryginalnej tablicy. A podobnie jak map(), filter() zwraca nową tablicę.


Składnia

var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])


Przykład

const array = [1,2,3,4,5];
const evenNumbers = array.filter(function(elem) {
   // expressions that return 'true' are retained
   return elem % 2 == 0;
});

5. find()


Kiedy używać?

Szukanie elementu w tablicy niekoniecznie musi oznaczać szukania igły w stogu siana. A to dlatego, że find() zwraca pierwszy element, który spełnia dany warunek. Po znalezieniu naszego elementu jest on natychmiast zwracany.


Składnia

arr.find(callback(element[, index[, array]])[, thisArg])


Przykład

const array = [1,4,4,5];
const result = array.find(function(elem, index) {
   console.log(`Index: ${index}`);
   return elem === 4;
});
console.log(`Result: ${result}`);
// Index: 0
// Index: 1
// Result: 4

6. some()


Kiedy używać?

Czasami chcemy wiedzieć, czy w tablicy jest co najmniej jeden element, który spełnia dane warunki. some() zwraca zatem wartość logiczną, która mówi nam, czy taki element istnieje.


Składnia

arr.some(callback(element[, index[, array]])[, thisArg])


Przykład

const array = [1,4,4,5];
const hasAtLeastAFour = array.some(function(elem) {
   return elem === 4;
});
console.log(hasAtLeastAFour);
// true

7. every()


Kiedy używać?

Czasem chcemy też wiedzieć, czy każdy element w tablicy spełnia określony warunek. every() zwraca zatem true, jeśli wszystkie elementy spełniają warunek - w przeciwnym wypadku dostaniemy false.


Składnia

arr.every(callback(element[, index[, array]])[, thisArg])


Przykład

const array = [1,4,4,5];
const allFours = array.every(function(elem) {
   return elem === 4;
});
console.log(allFours);
// false

Podsumowanie

W powyższych przykładach użyłem słowa kluczowego function, ale w ES6 możemy użyć funkcji strzałkowych, aby uzyskać krótszą składnię. Oprócz zwięzłości funkcje strzałkowe nie mają własnego this, co może być pomocne w zależności od sytuacji (np. przy użyciu zasięgu zewnętrznego).

array.forEach((elem, index) => {
    ...
});


Oto więc 7 funkcji wyższego rzędu, których regularnie używam. Więcej znajdziesz tutaj. Zwykle nie musisz tracić czasu na pisanie kodu od zera, ponieważ istnieją już natywne funkcje, które zrobią to za nas. Powinniśmy raczej starać się wykorzystać istniejące zasoby przed napisaniem kodu od zera.

Mam nadzieję, że ten artykuł był pomocny.

Oryginał tekstu w języku angielskim możesz przeczytać tutaj.


Masz jakieś przemyślenia? Podziel się nimi w komentarzu
?

<p>Loading...</p>