Metoda slice() w JavaScript to prosty sposób na wycięcie fragmentu tablicy albo napisu bez modyfikowania oryginału. W praktyce to jedno z tych narzędzi, które oszczędza najwięcej kodu przy paginacji, pracy na ostatnich elementach, tworzeniu podglądów i przycinaniu tekstu. Poniżej pokazuję, jak działa na tablicach i stringach, gdzie najłatwiej się pomylić oraz czym różni się od podobnych metod.
Najważniejsze rzeczy o slice(), które warto znać od razu
- Nie zmienia oryginału - zwraca nową tablicę albo nowy napis.
- End jest wyłączny - zakres kończy się przed wskazanym indeksem.
- Indeksy ujemne liczą od końca - to wygodne przy braniu ostatnich elementów.
- Na tablicach działa płytko - obiekty w środku nadal są współdzielonymi referencjami.
- Na stringach trzeba uważać na Unicode - szczególnie przy emoji i znakach łączonych.
-
Nie mylić ze
splice()- to inna metoda i inny efekt uboczny.
Jak działa slice() na tablicach
Na tablicach slice() wycina fragment od indeksu początkowego do końcowego i zwraca nową tablicę. Oryginał zostaje nietknięty, więc to bezpieczny wybór wszędzie tam, gdzie chcesz tylko odczytać zakres danych, a nie je modyfikować. Ja traktuję tę metodę jako podstawowe narzędzie do pracy na kawałkach list, bo kod od razu robi się czytelniejszy.
const fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
const citrus = fruits.slice(1, 3);
console.log(citrus); // ["Orange", "Lemon"]
console.log(fruits); // ["Banana", "Orange", "Lemon", "Apple", "Mango"]Najważniejsza zasada jest prosta: początek jest wliczony, koniec już nie. Jeśli podasz slice(1, 3), dostaniesz elementy z indeksów 1 i 2, ale nie ten z indeksu 3. To właśnie tu początkujący najczęściej robią błąd, bo intuicyjnie oczekują, że ostatni indeks też wejdzie do wyniku.
Przeczytaj również: npm init w Node.js - Jak zacząć projekt bez błędów?
Płytka kopia ma znaczenie
Na poziomie prostych wartości wszystko wygląda banalnie, ale przy tablicy obiektów ważny jest jeszcze jeden szczegół: slice() tworzy płytką kopię. To znaczy, że nowa tablica jest osobna, ale obiekty w środku nadal wskazują na te same referencje. Zmiana właściwości jednego obiektu będzie widoczna w obu tablicach.
const users = [
{ name: "Ala" },
{ name: "Bartek" },
{ name: "Celina" }
];
const firstTwo = users.slice(0, 2);
firstTwo[0].name = "Ania";
console.log(users[0].name); // "Ania"
console.log(firstTwo[0].name); // "Ania"To nie jest wada slice(), tylko cecha, o której trzeba pamiętać przy pracy z danymi zagnieżdżonymi. Jeśli potrzebujesz prawdziwej, głębokiej kopii, sam slice() nie wystarczy. Z tablicami jest to szczególnie ważne, a przy napisach dochodzi jeszcze temat znaków Unicode.
Jak działa slice() na napisach
Na stringach slice() działa podobnie, ale zwraca nowy napis. Ponieważ stringi w JavaScript są niemodyfikowalne, oryginał i tak pozostaje bez zmian. W praktyce metoda służy do wycinania fragmentu tekstu, np. prefiksu, końcówki, skróconego podglądu albo części identyfikatora.
const city = "Warszawa";
console.log(city.slice(0, 3)); // "War"
console.log(city.slice(3)); // "szawa"
console.log(city.slice(-3)); // "awa"Tu działa ta sama logika zakresu: start jest włączony, end wyłączony. Jeśli końca nie podasz, metoda bierze wszystko do końca napisu. To wygodne, gdy chcesz odciąć tylko początek albo tylko końcówkę.
Jest jednak ważny haczyk: w JavaScript stringi są oparte na UTF-16 code units, a nie na tym, co użytkownik widzi jako pojedynczy znak. Dlatego przy emoji, literach złożonych z kilku kodów albo tekstach z łącznikami i znakami diakrytycznymi można przypadkiem przeciąć znak w połowie. Jeśli potrzebujesz pracy na „ludzkich” znakach, lepszym kierunkiem bywa Intl.Segmenter, który dzieli tekst na graphemes, słowa albo zdania.
To już prowadzi do kolejnej rzeczy, która najbardziej miesza w głowie: indeksów dodatnich i ujemnych. Tam właśnie najłatwiej zobaczyć, jak slice() myśli o zakresie.

Jak czytać indeksy dodatnie i ujemne bez pomyłek
Indeksy dodatnie liczą od początku, a ujemne od końca. W praktyce oznacza to, że -1 wskazuje ostatni element, -2 przedostatni, i tak dalej. To bardzo wygodne, kiedy chcesz pobrać końcówkę listy albo odciąć ostatni znak z tekstu.
| Wywołanie | Co zwraca | Jak to czytać |
|---|---|---|
slice(2) |
od indeksu 2 do końca | Pomijasz dwa pierwsze elementy. |
slice(1, 4) |
elementy 1, 2, 3 | Koniec nie jest wliczony. |
slice(-2) |
dwa ostatnie elementy | Start liczony od końca. |
slice(1, -1) |
od drugiego elementu do przedostatniego | Przydatne przy „obcinaniu” boków. |
Warto też zapamiętać prostą regułę praktyczną: jeśli start wskazuje miejsce dalej niż end, wynik będzie pusty. To logiczne, ale właśnie takie przypadki najczęściej robią z kodu trudny do zdiagnozowania „nic nie zwraca”. Gdy dobrze rozumiesz indeksy, łatwiej porównać slice() z innymi metodami, a to oszczędza sporo czasu w codziennej pracy.
Czym slice() różni się od splice(), substring() i substr()
To jedno z najważniejszych porównań, bo nazwy są podobne, ale zachowanie już nie. Sam widziałem nie raz kod, w którym ktoś użył złej metody tylko dlatego, że „brzmiała podobnie”. W praktyce właśnie tu pojawia się najwięcej niepotrzebnych błędów.
| Metoda | Co robi | Modyfikuje oryginał | Najlepsze zastosowanie |
|---|---|---|---|
slice() |
Wycina zakres i zwraca nową wartość | Nie | Odcinanie fragmentu tablicy lub napisu |
splice() |
Usuwa lub wstawia elementy w tablicy | Tak | Zmiana zawartości tablicy „na miejscu” |
substring() |
Wyciąga fragment napisu | Nie | Proste wycinanie tekstu bez indeksów ujemnych |
substr() |
Wyciąga fragment od startu o określonej długości | Nie | Kod legacy, raczej do utrzymania starego projektu |
Najbardziej praktyczna różnica między slice() a substring() jest taka, że slice() rozumie indeksy ujemne, a substring() już nie. Dodatkowo substring() potrafi zamienić argumenty miejscami, jeśli pierwszy jest większy od drugiego, a slice() po prostu zwróci pusty wynik. To drobiazg, ale bardzo ważny, gdy zakres wyliczasz dynamicznie.
splice() zostawiam do sytuacji, w których naprawdę chcesz zmienić tablicę. Jeśli tylko czytasz dane, slice() jest bezpieczniejsze i przewidywalniejsze. A jeśli potrzebujesz wyciąć tylko jeden element, czasem lepsze będzie at(), bo jest po prostu prostsze.
Najczęstsze błędy przy pracy z slice()
Wbrew pozorom ta metoda psuje się nie przez sam kod, tylko przez błędne założenia. Poniżej są pułapki, które widzę najczęściej i które warto wyłapać od razu, zanim zaczną generować trudne do znalezienia błędy w aplikacji.
- Zakładanie, że metoda zmienia oryginał. Nie zmienia. Jeśli potrzebujesz mutacji, to nie jest właściwe narzędzie.
-
Mylenie końca zakresu z ostatnim elementem wyniku.
endjest wyłączny, więc zakres kończy się przed tym indeksem. - Traktowanie płytkiej kopii jak pełnego klona. Przy tablicach obiektów to różnica krytyczna.
- Ignorowanie znaków złożonych w stringach. Emoji i część znaków diakrytycznych mogą zostać przecięte w niefortunnym miejscu.
-
Używanie
slice()tam, gdzie lepiej pasuje filtracja. Jeśli wybór zależy od warunku, częściej potrzebujeszfilter(), a nie cięcia po indeksach.
Właśnie dlatego warto najpierw odpowiedzieć sobie na pytanie: czy tnę po pozycji, czy wybieram po regule? Gdy chodzi o pozycję, slice() jest świetne. Gdy chodzi o warunek, w grę wchodzą już inne narzędzia.
Kiedy używać slice(), a kiedy lepiej sięgnąć po inne narzędzie
Ja stosuję slice() przede wszystkim wtedy, gdy mam do czynienia z zakresem. To może być zakres elementów na liście produktów, zakres rekordów na stronie wyników, fragment nazwy pliku albo kawałek tekstu do podglądu. Jeśli zakres da się opisać indeksami, ta metoda zwykle jest najprostsza.
- Do paginacji i preview danych.
- Do pobierania ostatnich N elementów z tablicy.
- Do odcinania prefiksu lub sufiksu w stringu.
- Do tworzenia kopii tablicy na poziomie pierwszego poziomu.
- Do pracy z listą, w której nie chcesz naruszać źródła.
Po inne metody sięgam, gdy problem jest inny niż zwykłe wycinanie fragmentu. Jeśli chcesz pobrać tylko jeden element, rozważ at(). Jeśli rozdzielasz tekst po separatorze, bardziej pasuje split(). Jeśli filtrujesz po warunku, wybierz filter(). A jeśli pracujesz z tekstem, który trzeba dzielić po granicach widocznych znaków, a nie po surowych indeksach, lepszym kierunkiem jest Intl.Segmenter.
To podejście oszczędza mi sporo czasu w code review: zamiast pytać „czy to zadziała?”, pytam „czy to jest najczytelniejsza metoda dla tego zadania?”. W przypadku slice() odpowiedź bardzo często brzmi „tak”, ale tylko wtedy, gdy naprawdę tniesz po indeksach.
Co naprawdę warto zapamiętać przy slice()
Jeśli miałbym sprowadzić cały temat do kilku praktycznych reguł, powiedziałbym tak: slice() wycina zakres bez mutowania źródła, end jest wyłączny, a indeksy ujemne liczą od końca. To wystarcza do większości codziennych zastosowań i od razu rozbraja najczęstsze pomyłki.
- Na tablicach metoda zwraca nową tablicę.
- Na napisach zwraca nowy string.
- Przy tablicach z obiektami dostajesz kopię płytką, nie głęboką.
- Przy tekstach z emoji warto uważać na granice znaków.
- Gdy potrzebujesz zmiany „na miejscu”,
splice()jest inną klasą narzędzia.
W codziennym kodzie największą różnicę robi nie sama składnia, tylko świadomy wybór metody do zadania. Gdy rozumiesz, jak działa slice(), piszesz krócej, czytelniej i bez niepotrzebnych niespodzianek.