Tablice Javascript – 10 metod, które musisz znać

Javascript - 10 operacji na tablicach, które musisz znać

Tablice w języku Javascript są strukturami danych, z których korzysta się bez przerwy, dlatego ważna jest ich dobra znajomość. Metody, o których piszę w tym artykule, wykorzystuję na co dzień i uważam, że ich znajomość jest obowiązkowa.

1. map(fn)

map służy do transformacji danych. Jako argument przyjmuje funkcję fn(element, index, array) gdzie:

  • element – to aktualnie przetwarzany element tablicy
  • index – pozycja na której znajduje się aktualnie przetwarzany element
  • array – cała tablica

Wywołuje przekazaną funkcję na każdym elemencie tablicy. Wartość zwrócona z tej funkcji zostaje dodana do nowej tablicy. map nie zmienia oryginalnej tablicy i zawsze zwraca tablice tej samej długości co tablica na której została wywołana.

const nums = [1, 2, 3];

nums.map(num => num ** 3); // [1, 8, 27]

nums.map(
  (num, index) => num + index
); // [1, 3, 5]

nums.map(
  (num, index, array) => num + array[index]
); // [2, 4, 6]

nums // [1, 2, 3]

2. filter(fn)

Dzięki filter możemy wybrać tylko te elementy tablicy, które nas interesują. filter tak samo jak map przyjmuje funkcję fn(element, index, array), którą wywołuje na kolejnych elementach tablicy. Różnica jest taka, że funkcja przekazana do filter musi zwracać true lub false.

Elementy dla których przekazana funkcja zwróci true znajdą się w nowej tablicy, a reszta zostanie odrzucona.

const isEven = (num) => num % 2 === 0;
[1, 2, 3, 4].filter(isEven) // [2, 4]

3. reduce(fn, initialValue)

reduce jest najbardziej wszechstronną operacją na tablicy. Przyjmuje dwa argumenty:

  • funkcję, którą wywołuje na każdym elemencie fn(result, element, index, array), gdzie result to wynik wywołania funkcji z poprzednim elementem.
  • initialValue to wartość jaką przyjmie result dla pierwszego elementu tablicy
// map using reduce
[1, 2, 3].reduce(
  (result, num) => [...result, num ** 3],
  []
); // [1, 8, 27]

// filter using reduce
[1, 2, 3, 4].reduce(
  (result, num) => {
    if (num % 2 === 0) return [...result, num];
    return result;
  },
  []
); // [2, 4]

// sum using reduce
[1, 2, 3].reduce(
  (result, num) => result + num,
  0
); // 6

Korzystając z reduce jesteśmy w stanie zaimplementować każdą z metod znajdujących się na tej liście. Tak duże możliwości dają do myślenia. Może by tak zapomnieć o innych metodach i używać tylko reduce?

Moim zdaniem jest to bardzo zły pomysł. Przede wszystkim tracimy na czytelności kodu. Metody takie jak map czy filter niosą za sobą semantyczne znaczenie, co sprawia, że kod jest o wiele bardziej czytelny.

4. forEach(fn)

forEach jest metodą zdecydowanie rzadziej wykorzystywaną niż map, filter czy reduce, ale ma swoje zastosowania. Używamy jej wtedy, kiedy dla każdego elementu w tablicy chcemy wykonać jakąś operację. Jako argument przyjmuje funkcję fn(element, index, array).

forEach sprawdziłby się świetnie gdybyśmy musieli dodać klasę css do wszystkich przycisków na stronie.

const buttons = document.querySelectorAll('button');

buttons.forEach(button => 
  button.classList.add('hidden')
);

Należy pamiętać o tym, że forEach zawsze zwraca undefined.

const arr = [1, 2, 3];

const result = arr.forEach(num => {
  if (num === 2) {
    return num;
  }
});

result // undefined

5. includes(searchElement)

includes sprawdza czy dana wartość znajduję się w tablicy. Bardzo przydatna kiedy mamy do czynienia z typami prostymi.

[1, 2, 3].includes(2) // true
['a', 'b', 'c'].includes('a') // true
'ala ma kota'.includes('ala') // true

6. find(fn)

find działa na podobnej zasadzie co filter, jednak zwraca tylko jedną wartość zamiast listy wartości. Przyjmuję funkcję fn(element, index, array).W przypadku gdy żaden z elementów nie spełni warunku, zostanie zwrócone undefined.

find przydaje się najczęściej wtedy, gdy chcemy znaleźć jakiś obiekt mając jego unikalny identyfikator.

Mając identyfikator obiektu chcemy znaleźć go w naszej tablicy, aby dostać się do reszty jego atrybutów.

const products = [
  {
    name: "Coffee",
    id: 1
  },
  {
    name: "Chocolate",
    id: 2
  },
];

const product = products.find(product => product.id === 1);
product.name // Coffee

Należy pamiętać o tym, że find zwraca pierwszą wartość, która spełnia zadany warunek.

[1, 2, 3, 4].find(num => num > 1); // 2

7. findIndex(fn)

findIndex działa tak samo jak find. Jedyną różnicą, że zwraca indeks pod którym znajduje się znaleziona wartość.

const products = [
  {
    name: "Coffee",
    id: 1
  },
  {
    name: "Chocolate",
    id: 2
  },
];

products.findIndex(product => product.id === 1); // 0

8. some(fn)

some odpowiada na pytanie: Czy przynajmniej jeden element spełnia zadany warunek? Przyjmuje funkcję fn(element, index, array).

const products = [
  {
    name: "Coffee",
    available: true
  },
  {
    name: "Chocolate",
    available: false
  },
];

products.some(product => product.available); // true

9. every(fn)

every odpowiada na pytanie: Czy wszystkie elementy tablicy spełniają zadany warunek? Przyjmuje funkcję fn(element, index, array).

const products = [
  {
    name: "Coffee",
    available: true
  },
  {
    name: "Chocolate",
    available: false
  },
];

products.every(product => product.available); // false

10. sort()

sort służy do sortowania. Należy uważać, ponieważ ta metoda modyfikuje oryginalną tablicę. Najlepiej jest unikać mutacji. W tym celu możemy przed posortowaniem zrobić kopię tablicy.

const letters = ['c', 'b', 'a'];

const sortedLetters = [...letters].sort();

letters // ['c', 'b', 'a'];
sortedLetters // ['a', 'b', 'c'];

letters.sort();
letters // ['a', 'b', 'c']

sort domyślnie sortuje rosnąco z zachowaniem porządku alfabetycznego. Może to stwarzać problemy jeśli chcemy posortować liczby. Rozwiązaniem tego problemu jest przekazanie komparatora. Komparator to funkcja przyjmująca 2 elementy tablicy i zwracająca liczbę.

  • Jeśli compare(a, b) zwróci liczbę ujemną to w posortowanej tablicy a znajdzie się przed b
  • Jeśli compare(a, b) zwróci 0 to kolejność się nie zmieni
  • Jeśli compare(a, b) zwróci liczbę dodatnią to w posortowanej tablicy b znajdzie się przed a
const numbers = [8, 70, 600];

[...numbers].sort() // [600, 70, 8];

[...numbers].sort(
  (a, b) => a - b
); // [8, 70, 600];

Komparator może być bardzo skomplikowany. Mając listę uczestników konkursu chcemy ją posortować rosnąco po ilości punktów. Uczestnicy, którzy mają taką samą liczbę punktów powinni zostać posortowani po nazwisku.

const participants = [
  {
    points: 300,
    name: 'Krawczyk'
  },
  {
    points: 300,
    name: 'Fernandez'
  },
  {
    points: 280,
    name: 'Smith'
  }
];

function compareByPointsThenByName(a, b) {
  if (a.points !== b.points) {
    return a.points - b.points;
  }
  
  if (a.name > b.name) {
    return 1;  
  }

  if (a.name < b.name) {
    return -1;
  }
  
  return 0;
}

[...participants].sort(
  compareByPointsThenByName
) // 1. Smith, 2. Fernandez, 3. Krawczyk

Podsumowanie

Mam nadzieję, że metody o których pisałem pomogą Ci w codziennej pracy. W języku Javascript tablice są podstawowym narzędziem, które po prostu trzeba dobrze znać. W ramach treningu polecam sprawdzić Kurs Javascript 30 (dzień 4, 7, 18).

Pobierz darmowy ebook zawierający 20 pytań, które możesz usłyszeć na rozmowie kwalifikacyjnej