Menu

Tablice w JavaScript: tworzenie, dostęp, modyfikacja i iteracja

Jak działają tablice w JavaScript: tworzenie, indeksowanie, length, push/pop, slice vs splice i pętle, które czyta się najlepiej.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Tablica to uporządkowana lista

Tablice w JavaScript przechowują uporządkowaną sekwencję wartości. Wartości mogą być dowolnego typu (liczby, stringi, obiekty, a nawet inne tablice) i nie muszą być tego samego typu. Tablicę tworzysz za pomocą nawiasów kwadratowych:

Tej składni literału użyjesz w 99% przypadków. Istnieje też new Array(...), ale ma pułapkę: new Array(3) tworzy tablicę o długości 3 bez żadnych faktycznych elementów, a nie [3]. Trzymaj się [].

Indeksowanie zaczyna się od zera

Do elementów odwołujesz się po pozycji, licząc od 0:

Zwróć uwagę na dwie rzeczy. Po pierwsze, sięgnięcie poza koniec tablicy nie rzuca błędu, tylko zwraca undefined. To częste źródło błędów w stylu "czemu to jest undefined?". Po drugie, możesz przypisać wartość do dowolnego indeksu, także za końcem tablicy, a JavaScript chętnie ją rozszerzy:

Pozycje 3 i 4 stają się "pustymi miejscami" (dziurami w rzadkiej tablicy). Długość skacze do 6. Rzadko tego chcesz: to efekt uboczny elastyczności tablic, a nie funkcja, na której warto polegać.

length jest aktualizowane na bieżąco

array.length jest zawsze o jeden większe od najwyższego indeksu. Aktualizuje się automatycznie, gdy dodajesz lub usuwasz elementy:

Ostatnią sztuczkę warto zapamiętać: przypisanie do length przycina tablicę. Ustawienie nums.length = 0 to szybki sposób na opróżnienie jej w miejscu.

push, pop, shift, unshift

Cztery metody do dodawania i usuwania elementów na końcach tablicy:

  • push(x) dodaje na koniec i zwraca nową długość.
  • pop() usuwa z końca i zwraca usunięty element.
  • unshift(x) dodaje na początek.
  • shift() usuwa z początku.

push/pop są szybkie. shift/unshift muszą przenumerować wszystkie pozostałe elementy, więc na dużych tablicach są wolniejsze: przy codziennych rozmiarach nie ma to znaczenia, ale warto o tym wiedzieć, gdy pracujesz z milionami elementów.

slice vs splice

Te dwie metody mają podobne nazwy i zupełnie inne działanie. Jeśli je rozróżnisz, oszczędzisz sobie sporo drapania się po głowie.

slice(start, end) zwraca kopię fragmentu tablicy. Oryginał zostaje nietknięty. end nie wchodzi do wyniku:

splice(start, deleteCount, ...items) modyfikuje tablicę. Może usuwać, wstawiać albo jedno i drugie, a zwraca to, co usunęło:

Zasada praktyczna: slice to jak odkrojenie plasterka z bochenka, czyli kopia. Splice to jak montaż taśmy filmowej (wycinanie i wklejanie), czyli zmiana oryginału.

Wyszukiwanie: indexOf, includes, find

Trzy sposoby na wyszukanie czegoś, do różnych sytuacji:

  • indexOf(x) zwraca pozycję albo -1, jeśli nic nie znajdzie. Przydaje się, gdy potrzebujesz indeksu.
  • includes(x) zwraca wartość logiczną. Czytelniejsze, gdy chcesz tylko wiedzieć "czy to tu jest?". Poprawnie obsługuje też NaN, czego indexOf nie robi.
  • find(predicate) wywołuje funkcję dla każdego elementu i zwraca pierwszy pasujący. To wybór dla tablic obiektów, gdzie indexOf i includes sprawdzają tylko ścisłą równość.

Przechodzenie pętlą po tablicy

Kilka dobrych sposobów, każdy do innej sytuacji:

for...of to domyślny wybór: czytelny, działa z każdym obiektem iterowalnym i daje bezpośrednio wartość. forEach sprawdza się, gdy potrzebujesz też indeksu i nie przerywasz pętli wcześniej (z forEach nie da się wyjść przez break). Klasyczne for z indeksem jest rozwlekłe, ale daje pełną kontrolę: używaj go, gdy musisz pomijać elementy, iterować od końca albo jedno i drugie.

Pętla, której lepiej unikać: for...in. Iteruje po kluczach i uwzględnia odziedziczone właściwości. Służy do obiektów, nie do tablic.

Kopiowanie i łączenie

Tablice są wartościami referencyjnymi. Przypisanie jednej do drugiej nie tworzy kopii, tylko dwie nazwy dla tej samej tablicy:

Żeby naprawdę skopiować tablicę, użyj operatora spread albo slice():

Oba sposoby dają kopię płytką: tablica najwyższego poziomu jest nowa, ale jeśli elementy są obiektami, to te obiekty nadal są współdzielone. Spread to też najczytelniejszy sposób na łączenie tablic:

Tablice obiektów

W prawdziwym kodzie większość tablic przechowuje obiekty. Działają te same metody, ale dopasowywanie robi się ciekawsze:

filter zwraca nową tablicę elementów spełniających predykat. map zwraca nową tablicę, w której każdy element jest przekształcony. Łączenie ich w łańcuch to chleb powszedni pracy z tablicami obiektów, a następna strona dokumentacji omawia tę rodzinę metod dokładniej.

Tablice vs obiekty

Prosty model myślowy: używaj tablicy, gdy liczy się kolejność i pracujesz z listą rzeczy tego samego rodzaju. Używaj obiektu (albo Map), gdy odwołujesz się do rzeczy po nazwie. "Pierwszy, drugi, trzeci" to terytorium tablic. "Znajdź użytkownika o id 42" to terytorium obiektów albo Map.

Możesz je łączyć (tablice obiektów są wszędzie), ale nie używaj tablicy jako słownika z kluczami ani obiektu jako uporządkowanej listy. Każde z nich dobrze robi jedną rzecz.

Dalej: destrukturyzacja

Wyciąganie wartości z tablic po indeksie (i właściwości z obiektów po nazwie) zdarza się na tyle często, że JavaScript ma do tego osobną składnię. To destrukturyzacja i o niej jest następna strona.

Najczęściej zadawane pytania

Jak utworzyć tablicę w JavaScript?

Użyj literału z nawiasami kwadratowymi: const fruits = ['apple', 'banana']. To idiomatyczny sposób. Konstruktor Array (new Array(3)) istnieje, ale rzadko jest tym, czego chcesz: new Array(3) tworzy tablicę o długości 3 bez żadnych faktycznych elementów, co wiele osób zaskakuje.

Jak usunąć element z tablicy w JavaScript?

Z końca użyj pop(). Z początku użyj shift(). Ze środka użyj splice(index, 1), żeby zmienić tablicę w miejscu, albo filter(...), żeby dostać nową tablicę bez tego elementu. splice zmienia oryginał, filter nie.

Czym różni się slice od splice?

slice(start, end) zwraca płytką kopię fragmentu tablicy i zostawia oryginał w spokoju. splice(start, deleteCount, ...items) modyfikuje oryginał: usuwa elementy, opcjonalnie wstawia nowe i zwraca usunięte. Jedna litera różnicy, zupełnie inne działanie.

Jak sprawdzić, czy wartość jest w tablicy JavaScript?

Użyj array.includes(value): zwraca true albo false i poprawnie obsługuje NaN. indexOf(value) zwraca pozycję albo -1, jeśli nic nie znajdzie, co przydaje się, gdy potrzebujesz też indeksu. Przy bardziej złożonym dopasowaniu sięgnij po some(predicate) albo find(predicate).

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ