The Complete Guide to Reversing Text
Reversing text sounds trivial until you actually try to do it properly. This guide goes deeper on the interview question framing, Unicode edge cases at each level of the stack, and palindrome checking. For the basics of character vs word reversal and the Array.from() vs split('') gotcha, see the main article below the tool.
The classic interview question
"Reverse a string" is one of the most common coding interview questions, and the follow-up is always about Unicode. The textbook .split('').reverse().join('') breaks on emoji (as covered in the main article), but interviewers often push further:
Level 1 — use the spread operator or Array.from() to handle surrogate pairs. This is the minimum correct answer for any non-ASCII input.
Level 2 — handle grapheme clusters. The spread operator still splits compound emoji like 👨👩👧👦 (7 code points joined by Zero-Width Joiners). Show Intl.Segmenter:
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
const graphemes = [...segmenter.segment(str)].map(s => s.segment);
graphemes.reverse().join('');
Level 3 — discuss combining marks. The character é can be stored as a single code point (U+00E9) or as e + combining acute accent (U+0301). Without str.normalize('NFC') before reversing, the accent detaches and attaches to the wrong letter. Intl.Segmenter handles this correctly, but it's worth knowing why.
Flag emoji (🇺🇸 = two regional indicator code points) are another grapheme cluster edge case that only Intl.Segmenter handles.
Palindromes
A palindrome reads the same forwards and backwards: "racecar", "madam", "A man, a plan, a canal: Panama". Checking for palindromes is the most common practical use of character reversal.
In code, you need to normalize before comparing:
const clean = str.toLowerCase().replace(/[^a-z0-9]/g, '');
clean === [...clean].reverse().join('');
Strip punctuation, collapse case, then compare. Without normalization, "Racecar" would fail the check because R !== r.
Practical uses
Beyond interviews and palindromes, text reversal has real applications: debugging RTL (right-to-left) text rendering, creating mirror text effects for design work, reversing the order of log entries or list items, building text-based puzzles and cipher games, and generating test strings for Unicode handling in your own applications.
Troubleshooting
Emoji break when I reverse text — Most reversal methods split on UTF-16 code units, which tears apart multi-byte emoji. Use the spread operator ([...str]) or Intl.Segmenter for correct results.
Reversed text looks wrong with RTL languages — Arabic and Hebrew are naturally right-to-left. Reversing the characters produces text that appears left-to-right but is semantically broken. If you're debugging RTL rendering, reverse the visual display direction (CSS direction: rtl) rather than the character order.
Combining characters get separated from their base character — Characters like é can be composed of e + a combining acute accent (U+0301). Naive reversal splits them apart, attaching the accent to the wrong letter. Use str.normalize('NFC') to pre-compose characters before reversing, or use Intl.Segmenter to split by grapheme clusters.
Newlines in multiline text produce unexpected results — Character reversal treats \n as just another character, so line breaks end up in different positions. If you want to reverse each line independently, split on newlines first, reverse each line, then rejoin.