Metody slice() i splice() w JavaScript mają podobne nazwy, ale służą do zupełnie innych celów: slice() tworzy nową tablicę na podstawie fragmentu istniejącej, nie modyfikując oryginału, natomiast splice() modyfikuje tablicę w miejscu, usuwając i/lub dodając elementy.
Zapamiętaj: slice() nie zmienia źródła, a splice() je zmienia.
1. Dlaczego slice i splice tak często się mylą?
Obie metody działają podobnie na pierwszy rzut oka, bo:
- działają na tablicach JavaScript,
- operują na indeksach elementów,
- pozwalają „wyciąć” fragment tablicy.
Różnica jest jednak fundamentalna:
slice()– kopiuje fragment tablicy i zwraca go jako nową tablicę, nie zmieniając oryginalnej;splice()– modyfikuje oryginalną tablicę, usuwając i/lub dodając elementy od wskazanego indeksu; zwraca tablicę elementów usuniętych.
To rozróżnienie ma duże znaczenie w kontekście:
- architektury aplikacji (mutowalne vs niemutowalne struktury danych),
- projektowania komponentów UI,
- stabilności interfejsu i tym samym – pośrednio – dostępności (mniej trudnych do odtworzenia błędów w stanie aplikacji).
2. Wspólne cechy slice() i splice()
Zanim przejdziemy do szczegółów, warto zauważyć, co te metody mają wspólnego:
- są metodami prototypu
Array.prototype, czyli wywołujemy je na tablicach, np.numbers.slice(...), - operują na indeksach – dodatnie liczone są od początku (0, 1, 2, …), a ujemne od końca tablicy (…, -3, -2, -1),
- pozwalają pracować z fragmentami tablicy – ale robią to w zupełnie inny sposób.
To wspólne tło często sprawia, że początkujący programiści używają ich zamiennie, co szybko prowadzi do trudnych do znalezienia błędów.
3. slice() – metoda niemutująca
Co robi slice()?
Metoda slice() służy do wyodrębnienia fragmentu tablicy i zwrócenia go jako nową tablicę, bez modyfikowania oryginału.
Najważniejsze cechy:
- zwraca nową tablicę zawierającą elementy od indeksu
start(włącznie) doend(wyłącznie), - nie zmienia tablicy, na której została wywołana (jest niemutująca),
- może przyjmować wartości ujemne indeksów – wtedy są liczone od końca.
Sygnatura i parametry
Standardowa sygnatura:
Oto wywołanie z parametrami:
array.slice(start?, end?)
Najważniejsze informacje o parametrach:
start– indeks, od którego zaczynamy wycinanie (włącznie),- jeśli go nie podamy, przyjmowana jest wartość
0, - jeśli jest ujemny, liczymy od końca tablicy,
end(opcjonalny) – indeks, do którego wycinamy (bez elementu o tym indeksie),- jeśli go nie podamy, wycinamy do końca tablicy,
- jeśli jest ujemny, również liczymy od końca.
Proste przykłady
Przykład 1 – podstawowe użycie
Przykład w JavaScript:
const numbers = [10, 20, 30, 40, 50];
const part = numbers.slice(1, 4);
console.log(part); // [20, 30, 40]
console.log(numbers); // [10, 20, 30, 40, 50] – bez zmian
slice(1, 4) zwraca elementy o indeksach 1, 2, 3; element 4 jest wyłączony.
Przykład 2 – pomijanie end
Przykład w JavaScript:
const numbers = [10, 20, 30, 40, 50];
const fromIndex2 = numbers.slice(2);
console.log(fromIndex2); // [30, 40, 50]
console.log(numbers); // [10, 20, 30, 40, 50]
Brak parametru end oznacza „do końca tablicy”.
Przykład 3 – indeksy ujemne
Przykład w JavaScript:
const numbers = [10, 20, 30, 40, 50];
const lastTwo = numbers.slice(-2);
console.log(lastTwo); // [40, 50]
const middle = numbers.slice(1, -1);
console.log(middle); // [20, 30, 40]
Indeksy ujemne liczone są od końca tablicy.
slice() jako sposób na kopiowanie tablicy
Jeżeli wywołamy slice() bez argumentów, otrzymamy płytką kopię całej tablicy.
Przykład w JavaScript:
const original = ['a', 'b', 'c'];
const copy = original.slice();
copy.push('d');
console.log(original); // ['a', 'b', 'c']
console.log(copy); // ['a', 'b', 'c', 'd']
To popularny sposób na stworzenie niemutowalnej kopii (np. do pracy w stylu „immutable”).
Typowe zastosowania slice()
W praktyce slice() stosuje się m.in. gdy:
- potrzebujemy fragmentu danych bez zmiany oryginalnej tablicy (np. paginacja:
items.slice(offset, offset + limit)), - chcemy skopiować tablicę (np. do dalszego przetwarzania lub logowania historii),
- pracujemy w stylu funkcyjnym lub w bibliotekach preferujących niemutowalne struktury (np. React, Redux – to praktyczna konwencja, a nie cecha samego języka),
- chcemy wyliczyć „widok” danych (np. filtr + slice) bez ingerencji w źródło.
4. splice() – metoda mutująca
Co robi splice()?
Metoda splice() służy do dodawania, usuwania lub zastępowania elementów w tablicy, modyfikując ją bezpośrednio.
Najważniejsze cechy:
- działa w miejscu – zmienia oryginalną tablicę,
- może usuwać i dodawać elementy w dowolnym miejscu tablicy,
- zwraca nową tablicę zawierającą usunięte elementy (może być pusta),
- obsługuje indeksy ujemne, liczone od końca.
Sygnatura i parametry
Standardowa sygnatura:
Oto wywołanie z parametrami:
array.splice(start, deleteCount?, ...itemsToAdd)
Najważniejsze informacje o parametrach:
start– indeks, od którego zaczynamy modyfikację,- jeśli jest ujemny, liczymy od końca tablicy,
deleteCount(opcjonalny) – ile elementów usunąć od indeksustart,- jeśli
deleteCountnie zostanie podany, usuwane są wszystkie elementy odstartdo końca tablicy, - jeśli wynosi
0, żaden element nie jest usuwany – można tylko dodawać, ...itemsToAdd– dowolna liczba elementów do wstawienia w miejscu usuniętych; każdy kolejny argument jest kolejnym dodanym elementem.
Usuwanie elementów
Przykład 1 – usunięcie kilku elementów
Przykład w JavaScript:
const numbers = [10, 20, 30, 40, 50];
const removed = numbers.splice(1, 2);
console.log(removed); // [20, 30] – usunięte elementy
console.log(numbers); // [10, 40, 50] – oryginalna tablica zmieniona
Tutaj od indeksu 1 usuwamy 2 elementy, czyli 20 i 30.
Przykład 2 – usuwanie do końca tablicy
Przykład w JavaScript:
const numbers = [10, 20, 30, 40, 50];
const removed = numbers.splice(2);
console.log(removed); // [30, 40, 50]
console.log(numbers); // [10, 20]
Brak deleteCount oznacza usunięcie od start (2) do końca tablicy.
Dodawanie elementów
Przykład 3 – wstawienie elementów bez usuwania
Przykład w JavaScript:
const letters = ['a', 'd'];
letters.splice(1, 0, 'b', 'c');
console.log(letters); // ['a', 'b', 'c', 'd']
deleteCount = 0, więc nic nie usuwamy, a pod indeks 1 wstawiamy 'b' i 'c'.
Zastępowanie elementów
Przykład 4 – podmiana istniejących wartości
Przykład w JavaScript:
const letters = ['a', 'x', 'y', 'd'];
const removed = letters.splice(1, 2, 'b', 'c');
console.log(removed); // ['x', 'y']
console.log(letters); // ['a', 'b', 'c', 'd']
Usuwamy 2 elementy od indeksu 1 i w ich miejsce wstawiamy dwa nowe.
Indeksy ujemne
Przykład w JavaScript:
const numbers = [10, 20, 30, 40, 50];
numbers.splice(-2, 1); // start = -2 => indeks 3 (40)
console.log(numbers); // [10, 20, 30, 50]
Ujemny start liczy pozycję od końca tablicy.
Typowe zastosowania splice()
splice() wybieramy, gdy intencją jest modyfikacja istniejącej tablicy, np.:
- edycja danych w miejscu (usuwanie rekordów, wstawianie nowych, reorganizacja listy),
- implementacja logiki, gdzie aktualizacja tablicy ma być natychmiast odzwierciedlona przez wszystkie referencje (np. proste skrypty, bez zaawansowanego zarządzania stanem),
- budowanie struktury danych krok po kroku, gdy mutacje są akceptowalne.
5. slice() vs splice() – porównanie
Poniższa tabela syntetyzuje kluczowe różnice między metodami:
| Cechy / pytanie | slice() |
splice() |
|---|---|---|
| Czy modyfikuje oryginalną tablicę? | Nie – zwraca nową tablicę, oryginał pozostaje bez zmian. | Tak – działa „w miejscu”, zmienia oryginalną tablicę. |
| Co zwraca? | Nową tablicę z wybranymi elementami. | Tablicę usuniętych elementów (może być pusta). |
| Główny cel | Wyodrębnienie fragmentu tablicy / kopia niemutowalna. | Usuwanie, dodawanie, zastępowanie elementów w tablicy. |
| Typ operacji | Niemutująca (nie zmienia źródła). | Mutująca (zmienia źródło). |
| Liczba argumentów | 0–2 (start, end). | 1–n (start, deleteCount, …elements). |
Znaczenie indeksu end |
Nie wlicza elementu o indeksie end. |
Brak parametru end; używamy deleteCount. |
| Możliwość dodawania elementów | Nie – tylko odczyt/kopia fragmentu. | Tak – można wstawiać dowolną liczbę elementów. |
| Obsługa indeksów ujemnych | Tak – liczone od końca tablicy. | Tak – liczone od końca tablicy. |
| Typowe użycie | Paginalizacja, wyświetlanie fragmentu, kopia tablicy. | Edycja danych „na miejscu” – usuwanie/insert/replace rekordów. |
Jeśli nie chcesz zmieniać oryginalnej tablicy, użyj slice().
Jeśli chcesz ją zmienić (usunąć/dodać elementy), użyj splice().
6. Wpływ na architekturę aplikacji i dostępność
Mutowalność a złożone interfejsy
W większych aplikacjach webowych (SPA, PWA) stan interfejsu jest często przechowywany jako złożone drzewo obiektów i tablic. Używanie metod, które mutują stan (jak splice()), utrudnia śledzenie, kiedy i gdzie dana struktura została zmodyfikowana. To nie jest bezpośrednio opisane w specyfikacji, ale wynika z praktyki projektowej.
Niemutujące metody (jak slice()) ułatwiają pracę, ponieważ:
- ułatwiają debugowanie (zawsze widzimy „starą” i „nową” wersję),
- ułatwiają porównywanie stanu przed/po (np.
prevState !== nextState), - zmniejszają ryzyko nieoczekiwanych efektów ubocznych.
To jest szczególnie istotne w bibliotekach takich jak React czy Redux, gdzie niemutowalność stanu jest ważną konwencją – wynika to z ogólnych zasad tych narzędzi, a nie z samego faktu istnienia slice() i splice().
Stabilność UI a dostępność
Błędy wynikające z niekontrolowanej mutacji tablic (np. usunięcie elementu, ale brak aktualizacji powiązanych struktur) mogą skutkować:
- nieprawidłowym fokusem klawiatury (focus przeskakuje w nieoczekiwane miejsce),
- niespójnymi etykietami ARIA lub opisami elementów,
- niespójnością między treścią wizualną a strukturą DOM, którą odczytuje czytnik ekranu.
Choć same metody slice() i splice() nie są „narzędziami dostępności”, to kontrolowanie mutacji stanu za pomocą odpowiednich metod zmniejsza ryzyko błędów, które bezpośrednio uderzają w użytkowników korzystających z technologii asystujących.
7. Typowe błędy i pułapki
Pomylenie slice ze splice (i odwrotnie)
To najczęstszy błąd. Zobacz, co się dzieje, gdy przez pomyłkę użyjesz splice():
const items = [1, 2, 3, 4];
// Intencja: usunąć element o indeksie 1 bez modyfikowania oryginału
const result = items.splice(1, 1); // BŁĄD: wynik i tablica będą inne niż oczekiwano
console.log(result); //
console.log(items); // [1, 3, 4] – tablica została zmieniona!
Jeśli celem było utworzenie nowej tablicy bez elementu o indeksie 1, lepiej zastosować podejście niemutujące:
Przykład w JavaScript:
const items = [1, 2, 3, 4];
const result = [...items.slice(0, 1), ...items.slice(2)];
console.log(result); // [1, 3, 4]
console.log(items); // [1, 2, 3, 4] – bez zmian
Nieprawidłowe rozumienie parametru end w slice()
W slice(start, end) element o indeksie end jest wykluczony. Przykład:
const numbers = [0, 1, 2, 3, 4];
console.log(numbers.slice(1, 4)); // [1, 2, 3], a nie [1, 2, 3, 4]
To klasyczna pułapka off-by-one.
Zapomnienie, że splice() zwraca usunięte elementy
Początkujący czasem oczekują, że wynik splice() będzie „nową tablicą bez usuniętych elementów”, podczas gdy jest to tablica z elementami usuniętymi. Przykład:
const items = ['a', 'b', 'c'];
const result = items.splice(1, 1); // Wynik: result = ['b'], items = ['a', 'c']
Indeksy ujemne w slice() i splice()
Ujemne indeksy są liczone od końca tablicy. Przykłady użycia:
const numbers = [10, 20, 30, 40];
console.log(numbers.slice(0, -1)); // [10, 20, 30]
W przypadku splice(-1, 1) usuniemy ostatni element:
const numbers = [10, 20, 30, 40];
numbers.splice(-1, 1);
console.log(numbers); // [10, 20, 30]
8. Przykłady praktyczne z perspektywy front‑endu
Paginalizacja listy – idealne dla slice()
Wyobraźmy sobie listę artykułów pobranych z API. Tak można wyliczyć dany „widok” strony:
const articles = [/* ...dużo obiektów... */];
const page = 2;
const perPage = 10;
const start = (page - 1) * perPage;
const end = start + perPage;
const visibleArticles = articles.slice(start, end);
Oryginalna tablica articles pozostaje nietknięta.
visibleArticles to nowa tablica, którą można bezpiecznie przekazać np. do komponentu widoku.
Usuwanie elementu z listy edytowalnej – splice()
Dla prostej listy zarządzanej „ręcznie” mutacja może być świadoma i pożądana:
const todoList = ['Zadanie 1', 'Zadanie 2', 'Zadanie 3'];
function removeTodo(index) {
const removed = todoList.splice(index, 1);
console.log('Usunięto:', removed);
}
removeTodo(1);
console.log(todoList); // ['Zadanie 1', 'Zadanie 3']
Aktualizacja stanu w bibliotece nastawionej na niemutowalność
W środowisku, gdzie nie chcemy mutować stanu (np. React + Redux), możemy stosować slice() i operator rozproszenia:
function removeTodoImmutable(todos, index) {
return [
...todos.slice(0, index),
...todos.slice(index + 1),
];
}
const todos = ['A', 'B', 'C'];
const newTodos = removeTodoImmutable(todos, 1);
console.log(todos); // ['A', 'B', 'C']
console.log(newTodos); // ['A', 'C']
9. Powiązane metody: slice, splice i split
W kontekście nazewnictwa często pojawia się jeszcze jedna metoda: split(). Oto szybkie porównanie:
slice()– metoda tablicowa; kopiuje fragment tablicy, nie mutuje oryginału,splice()– metoda tablicowa; dodaje/usuwa elementy, mutuje oryginał,split()– metoda łańcuchów znaków, która dzieli string na tablicę według separatora.
split() przyjmuje separator (np. spację lub przecinek) i zwraca nową tablicę fragmentów tekstu, ale w przeciwieństwie do slice()/splice() jest wywoływana na stringu, nie na tablicy.
10. Wskazówki dla junior developerów
-
Ucz się rozpoznawać mutację stanu:
jeśli metoda modyfikuje oryginalną tablicę (jak
splice()), używaj jej tylko wtedy, gdy jest to w pełni świadome i pożądane; w złożonych aplikacjach częściej preferuj metody niemutujące (slice(),map(),filter()). -
Stosuj
slice()do „bezpiecznych” operacji:- wyświetlanie fragmentu listy (paginacja, „Pokaż więcej”),
- kopia tablicy przed modyfikacją (np. do historii zmian),
- generowanie nowych struktur danych z istniejących.
-
Stosuj
splice()do modyfikacji w miejscu:- gdy zarządzasz prostym stanem (np. mały skrypt, brak frameworka),
- gdy chcesz, aby wszystkie referencje do tablicy widziały tę samą zmianę,
- gdy edytujesz listy w strukturach danych, w których mutowalność jest dopuszczalna.
-
Czytelność ważniejsza niż oszczędność znaków:
czasem bardziej rozbudowane rozwiązanie z
slice()i operatorem rozproszenia jest bezpieczniejsze i czytelniejsze niż jedna linijka z użyciemsplice(), zwłaszcza gdy kod ma być utrzymywany przez większy zespół. -
Uważaj na parametry i ich kolejność:
slice(start, end)– end jest wyłączny.splice(start, deleteCount, ...items)– deleteCount określa ile usunąć, a dopiero potem podajesz elementy do dodania.






