Temat js reverse w praktyce sprowadza się do dwóch różnych problemów: odwracania tablic i odwracania napisów. Ja zwykle rozdzielam je od razu, bo tablica może zostać zmieniona „w miejscu”, a tekst jest niezmienny i wymaga innych metod. W tym tekście pokazuję, kiedy użyć reverse(), kiedy lepiej sięgnąć po toReversed(), oraz dlaczego przy stringach prosty trik z split("") bywa zdradliwy.
Kluczowe informacje, które uporządkują temat od razu
-
reverse()odwraca tablicę w miejscu i zwraca tę samą referencję. -
toReversed()tworzy nową tablicę, więc nie psuje oryginału. - W JavaScript nie ma metody
string.reverse(); napis trzeba najpierw przekształcić. -
split("")działa prosto, ale może uszkodzić znaki Unicode, zwłaszcza emoji. - Do tekstu użytkownika najbezpieczniejszy jest
Intl.Segmenterz granularitygrapheme. - Wszystkie te operacje są liniowe, więc koszt rośnie wraz z długością danych.

Jak bezpiecznie odwrócić tablicę
W tablicach wybór jest prosty, ale tylko jeśli wiesz, czy chcesz zmienić źródło danych. reverse() modyfikuje tablicę w miejscu, a toReversed() zwraca nową kopię z odwróconą kolejnością. To różnica, która w zwykłym skrypcie bywa niewidoczna, ale w kodzie aplikacji potrafi zabić przewidywalność stanu.
reverse() gdy chcesz zmienić oryginał
To dobra opcja, gdy tablica ma zostać odwrócona naprawdę, a nie tylko „na chwilę” do wyświetlenia. Najważniejsze jest to, że metoda zwraca tę samą tablicę, więc nie tworzysz nowego obiektu.
const numbers = [1, 2, 3, 4];
const reversed = numbers.reverse();
console.log(numbers); // [4, 3, 2, 1]
console.log(reversed); // [4, 3, 2, 1]
console.log(reversed === numbers); // trueTo ważne, bo jeśli później zmienisz reversed, zmienisz też numbers. W kodzie z Reactem, Reduxem albo innym stanem reaktywnym taka mutacja bywa źródłem trudnych do śledzenia błędów.
toReversed() gdy oryginał ma zostać nienaruszony
Jeśli nie chcesz dotykać wejściowych danych, ten wariant jest zwykle lepszy. Dostajesz nową tablicę, a stara zostaje taka sama, co jest dużo bezpieczniejsze w kodzie funkcyjnym i w warstwie UI.
const numbers = [1, 2, 3, 4];
const reversed = numbers.toReversed();
console.log(numbers); // [1, 2, 3, 4]
console.log(reversed); // [4, 3, 2, 1]Ja traktuję toReversed() jako domyślny wybór tam, gdzie liczy się przewidywalność. Jeśli pracujesz w starszym środowisku, trzeba zostać przy kopii tworzonej przed odwróceniem albo użyć polyfillu.
Kopia przed reverse() jako opcja zgodna ze starszym kodem
Najczęściej spotkasz zapis z slice(), bo tworzy płytką kopię tablicy, a potem pozwala ją odwrócić bez ruszania oryginału. Dla zwykłych, gęstych tablic działa to dobrze i jest czytelne.
const numbers = [1, 2, 3, 4];
const reversed = numbers.slice().reverse();
console.log(numbers); // [1, 2, 3, 4]
console.log(reversed); // [4, 3, 2, 1]Warto wiedzieć jeszcze jedno: reverse() zachowuje puste sloty w sparse arrays, a toReversed() zamienia je na undefined. Dla zwykłych list nie ma to znaczenia, ale przy nietypowych danych różnica jest realna.
Tablica jest prosta. Przy napisach zaczynają się schody, bo tu dochodzi Unicode, a od tego zależy, czy prosty skrót będzie poprawny.
Jak odwrócić napis bez psucia znaków
W przypadku stringów nie ma bezpośredniej metody reverse(), więc trzeba najpierw zamienić tekst na coś, co da się przestawić. Najkrótszy zapis działa dla prostych przypadków, ale nie zawsze daje poprawny wynik wizualny.
Najprostszy wariant działa tylko dla prostych znaków
To klasyczny trik, który często pojawia się w ćwiczeniach i na początku nauki. Dla zwykłego ASCII jest w porządku, bo każdy znak jest jednoznaczny.
const text = "kot";
const reversed = text.split("").reverse().join("");
console.log(reversed); // "tok"Problem zaczyna się tam, gdzie tekst zawiera znaki spoza podstawowego zakresu albo złożone emoji. split("") pracuje na UTF-16 code units, więc może rozciąć jeden znak na pół i zepsuć wynik.
Spread syntax jest bezpieczniejszy dla kodpunktów
Jeśli chcesz odwrócić napis z większą szansą na poprawny efekt, lepiej rozbić go operatorem spread. Taki zapis iteruje po Unicode code points, więc nie niszczy surrogate pairs.
const text = "Zażółć gęślą jaźń";
const reversed = [...text].reverse().join("");
console.log(reversed);To rozwiązanie jest wyraźnie lepsze od split(""), ale nadal nie rozwiązuje wszystkiego. Są znaki, które użytkownik widzi jako jedną literę lub jeden symbol, a technicznie składają się z kilku kodpunktów.
Przeczytaj również: hasOwnProperty w JS – jak sprawdzić własność obiektu?
Intl.Segmenter daje najlepszy efekt dla tekstu użytkownika
Jeśli odwracasz napis, który może zawierać emoji, flagi albo znaki łączone, najlepszym wyborem jest segmentacja po grapheme clusters. To najbliższe temu, jak człowiek widzi pojedynczy znak.
const text = "👨👩👧👦 cześć";
const segmenter = new Intl.Segmenter("pl", { granularity: "grapheme" });
const reversed = Array.from(segmenter.segment(text), ({ segment }) => segment)
.reverse()
.join("");
console.log(reversed);To wariant, który traktuję jako najbezpieczniejszy przy treściach widocznych dla użytkownika. Kosztuje trochę więcej kodu, ale daje wynik zgodny z tym, co naprawdę widać na ekranie.
Gdy już znasz różnicę między tablicą a napisem, pozostaje wybrać metodę według sytuacji, a nie według przyzwyczajenia.
Którą metodę wybrać w praktyce
W codziennym kodzie nie wybieram metody według tego, która jest najkrótsza, tylko według tego, czy wolno mi zmienić oryginał, czy pracuję z tekstem użytkownika i czy środowisko wspiera nowsze API. Ta prosta tabela porządkuje wybór szybciej niż długie rozważania.
| Sytuacja | Najlepszy wybór | Co zyskujesz | Na co uważać |
|---|---|---|---|
| Tablica ma zostać zmieniona w miejscu | reverse() |
Brak dodatkowej kopii | Zmienia oryginalne dane |
| Chcesz zachować oryginał tablicy | toReversed() |
Nową tablicę bez efektów ubocznych | Wymaga nowoczesnego środowiska |
| Potrzebujesz zgodności w starszym kodzie | arr.slice().reverse() |
Bezpieczną kopię przed odwróceniem | To nadal kopia płytka |
| Prosty napis ASCII | [...text].reverse().join("") |
Czytelny zapis i dobry wynik | Nie chroni przed złożonymi znakami |
| Tekst z emoji i znakami łączonymi | Intl.Segmenter |
Najbardziej naturalny efekt dla użytkownika | Więcej kodu i zależność od wsparcia API |
| Chcesz tylko ostatni element tablicy | at(-1) |
Bez niepotrzebnego odwracania całości | Działa odczytowo, nie przestawia danych |
Każdy z tych wariantów działa w czasie liniowym, więc przy małych kolekcjach różnica jest kosmetyczna. Prawdziwa decyzja dotyczy tego, czy mutujesz dane, czy tworzysz kopię, i czy odwracasz zwykły tekst, czy Unicode, który nie wybacza skrótów.
Najczęstsze błędy, które widzę w kodzie
Najbardziej kosztowne pomyłki przy odwracaniu kolejności są zwykle proste, ale trudne do zauważenia podczas szybkiego przeglądu kodu. Problem nie polega na tym, że metoda nie działa, tylko na tym, że działa za dobrze i zmienia coś, czego nie planowałeś zmienić.
-
Mylenie mutacji z kopią.
reverse()zmienia oryginalną tablicę, więc nie nadaje się tam, gdzie dalej korzystasz z tych samych danych. -
Oczekiwanie, że napis ma metodę
reverse(). String w JavaScript jest niezmienny, więc trzeba go najpierw przekształcić do struktury, którą da się odwrócić. -
Używanie
split("")na każdym tekście. Dla prostych słów zadziała, ale przy emoji, znakach łączonych i części zapisów Unicode efekt bywa błędny. -
Zapominanie o płytkiej kopii.
toReversed()i kopiowanie przedreverse()nie klonują obiektów wewnątrz tablicy, tylko samą tablicę. -
Odwracanie tablicy tylko po to, by pobrać ostatni element. Jeśli potrzebujesz jednego elementu, użyj
at(-1)albo odpowiedniego indeksu od końca. - Mutowanie stanu w React albo Redux. W aplikacjach webowych to częsty powód dziwnych renderów i trudnych do odtworzenia błędów.
const users = [{ name: "Ala" }, { name: "Ola" }];
const reversed = users.toReversed();
reversed[0].name = "Zmienione";
console.log(users[1].name); // "Zmienione"Ten przykład dobrze pokazuje, że odwrócenie kolejności nie oznacza automatycznie odseparowania danych. Jeśli elementy są obiektami, nadal współdzielisz te same referencje, więc zmiany w środku mogą wracać do źródła.
Po tych pułapkach zostaje już tylko zestaw prostych reguł, które pozwalają wybrać dobrą metodę bez zastanawiania się za każdym razem od nowa.
Reguły, które pozwalają wybrać dobrą metodę za pierwszym razem
Ja trzymam się trzech prostych zasad. Po pierwsze, jeśli pracuję na tablicy i chcę zmienić dane świadomie, biorę reverse(). Po drugie, jeśli kod ma być przewidywalny i bez efektów ubocznych, wybieram toReversed(). Po trzecie, jeśli odwracam napis, najpierw sprawdzam, czy to zwykły ASCII, czy tekst użytkownika z Unicode, bo od tego zależy, czy wystarczy spread, czy potrzebny jest Intl.Segmenter.
W praktyce to wystarcza w większości projektów webowych: tablice odwracasz świadomie, napisy odwracasz ostrożnie, a przy tekstach z emoji nie liczysz na skrótowe triki. Jeśli zapamiętasz tylko tę różnicę, unikniesz większości cichych błędów i nie będziesz poprawiać kodu po wdrożeniu.