JavaScript slice() - Jak ciąć tablice i stringi bez błędów?

Diagram przedstawia metodę JavaScript slice(), która tworzy płytką kopię danych typu Array/String, zachowując oryginalną integralność.

Napisano przez

Jacek Zając

Opublikowano

25 mar 2026

Spis treści

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.

Diagram przedstawia różne sposoby manipulacji danymi w JavaScript, w tym js slice do pobierania, usuwania i kopiowania elementów z tablic oraz obiektów.

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. end jest 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 potrzebujesz filter(), 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.

FAQ - Najczęstsze pytania

slice() tworzy nową tablicę lub string z wybranym fragmentem, nie modyfikując oryginału. splice() natomiast zmienia oryginalną tablicę, dodając, usuwając lub zastępując jej elementy. To kluczowa różnica w kontekście mutacji danych.

Nie, slice() tworzy płytką kopię. Oznacza to, że nowa tablica zawiera te same referencje do obiektów, co oryginalna. Zmiana właściwości obiektu w jednej tablicy będzie widoczna również w drugiej.

Indeksy ujemne w slice() liczone są od końca tablicy lub stringa. Na przykład, -1 oznacza ostatni element, -2 przedostatni itd. Jest to bardzo przydatne do łatwego wycinania końcowych fragmentów.

slice() i substring() są podobne, ale slice() obsługuje indeksy ujemne, co jest jego główną przewagą. substring() potrafi też zamienić argumenty, jeśli początkowy indeks jest większy niż końcowy, co może prowadzić do nieoczekiwanych wyników.

slice() działa na jednostkach kodu UTF-16, a nie na widocznych znakach (graphemes). Może to prowadzić do "przecięcia" emoji lub znaków złożonych. Dla precyzyjnej pracy ze znakami Unicode, rozważ użycie Intl.Segmenter.

Oceń artykuł

Ocena: 0.00 Liczba głosów: 0

Tagi:

js slice javascript slice przykład slice array javascript

Udostępnij artykuł

Jacek Zając

Jacek Zając

Nazywam się Jacek Zając i od dziewięciu lat zajmuję się programowaniem webowym. Moja przygoda z tą dziedziną zaczęła się od fascynacji tworzeniem stron internetowych, co szybko przerodziło się w pasję do nauczania innych. Lubię dzielić się wiedzą i pomagać osobom, które stawiają pierwsze kroki w programowaniu. Skupiam się na wyjaśnianiu złożonych zagadnień w przystępny sposób, aby każdy mógł zrozumieć podstawy i rozwijać swoje umiejętności. W moich artykułach poruszam różnorodne tematy związane z programowaniem webowym, od HTML i CSS po JavaScript i frameworki. Dokładam wszelkich starań, aby informacje, które prezentuję, były rzetelne, aktualne i łatwe do przyswojenia. Regularnie śledzę nowinki w branży, co pozwala mi na dostarczanie czytelnikom treści zgodnych z najnowszymi trendami. Wierzę, że dobrze zorganizowana wiedza to klucz do sukcesu w karierze programisty.

Napisz komentarz