How do you reverse a string in-place in JavaScript when it is passed to a function with a return statement, without using built-in functions (.reverse()
, .charAt()
etc.)?

- 21,987
- 6
- 62
- 97
-
so, you're not allowed to use .charAt() to get the characters of the string? – Irwin Jun 06 '09 at 03:27
-
190You can't. JavaScript strings are immutable, meaning the memory allocated to each cannot be written to, making true "in place" reversals impossible. – Crescent Fresh Jun 06 '09 at 04:36
-
3Re: crescentfresh's comment see http://stackoverflow.com/questions/51185/are-javascript-strings-immutable-do-i-need-a-string-builder-in-js – baudtack Jun 06 '09 at 05:25
-
3@crescentfresh you should post that as a new answer. – baudtack Jun 06 '09 at 05:47
-
@Irwin, its 2015 and charAt() still isn't fully supported. where it is supported it's slow. – Octopus Jun 05 '15 at 21:22
-
2[Reverse a string in 3 ways in Javascript](https://medium.freecodecamp.com/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb#.lsmvejm8o) – Somnath Muluk Sep 12 '16 at 07:12
-
```var reverse = (str, rev = '') => str.length == 0 ? console.log(rev) : reverse((str.substr(0,str.length -1)), (rev + str.substr(str.length -1 , 1)));``` – Akash Vishwakarma Jun 28 '19 at 07:00
-
[reverse string in js](https://www.youtube.com/watch?v=j_zyN0aPoGU) – InfiniteStack Jun 06 '22 at 15:35
56 Answers
As long as you're dealing with simple ASCII characters, and you're happy to use built-in functions, this will work:
function reverse(s){
return s.split("").reverse().join("");
}
If you need a solution that supports UTF-16 or other multi-byte characters, be aware that this function will give invalid unicode strings, or valid strings that look funny. You might want to consider this answer instead.
The array expansion operator is Unicode aware:
function reverse(s){
return [...s].reverse().join("");
}
Another Unicode aware solution using split()
, as explained on MDN, is to use a regexp with the u
(Unicode) flag set as a separator.
function reverse(s){
return s.split(/(?:)/u).reverse().join("");
}
-
52This is broken for UTF-16 strings that contain surrogate pairs, i.e. characters outside of the basic multilingual plane. It will also give funny results for strings containing combining chars, e.g. a diaeresis might appear on the following character. The first issue will lead to invalid unicode strings, the second to valid strings that look funny. – Martin Probst Apr 10 '13 at 13:21
-
2@Richeve Bebedor "All without using the built-in functions? .reverse()" This would not be an accepted solution since it does not fit within the confines of the question, despite being a viable solution to reversing a string in JS. – David Starkey Apr 30 '13 at 18:06
-
2@DavidStarkey: Yes, looking back on this almost four years later, it's hard to see how I so thoroughly missed the point of the question. It looks like I should've just waited two minutes and upvoted crescentfresh's comment on the original post! – belacqua May 02 '13 at 02:04
-
16@MartinProbst My answer provides a Unicode-aware solution to the problem that deals with surrogate pairs and combining marks correctly: http://stackoverflow.com/a/16776380/96656 – Mathias Bynens May 27 '13 at 15:45
-
-
6
-
1And it’s not in-place `string` reversing, which is not possible. – Константин Ван Jun 29 '19 at 08:05
-
-
Why can't we just do: Array.prototype.reverse.call(string) ? like .filter works this way on strings... – RegarBoy Jul 24 '21 at 08:37
-
Because strings are immutable. Reverse is trying to mutate an array and cannot, because it's a string. Filter does not mutate an array, it makes another one. So it works – Anton Chukanov Sep 09 '21 at 05:47
The following technique (or similar) is commonly used to reverse a string in JavaScript:
// Don’t use this!
var naiveReverse = function(string) {
return string.split('').reverse().join('');
}
In fact, all the answers posted so far are a variation of this pattern. However, there are some problems with this solution. For example:
naiveReverse('foo bar');
// → 'rab �� oof'
// Where did the `` symbol go? Whoops!
If you’re wondering why this happens, read up on JavaScript’s internal character encoding. (TL;DR: is an astral symbol, and JavaScript exposes it as two separate code units.)
But there’s more:
// To see which symbols are being used here, check:
// http://mothereff.in/js-escapes#1ma%C3%B1ana%20man%CC%83ana
naiveReverse('mañana mañana');
// → 'anãnam anañam'
// Wait, so now the tilde is applied to the `a` instead of the `n`? WAT.
A good string to test string reverse implementations is the following:
'foo bar mañana mañana'
Why? Because it contains an astral symbol () (which are represented by surrogate pairs in JavaScript) and a combining mark (the
ñ
in the last mañana
actually consists of two symbols: U+006E LATIN SMALL LETTER N and U+0303 COMBINING TILDE).
The order in which surrogate pairs appear cannot be reversed, else the astral symbol won’t show up anymore in the ‘reversed’ string. That’s why you saw those ��
marks in the output for the previous example.
Combining marks always get applied to the previous symbol, so you have to treat both the main symbol (U+006E LATIN SMALL LETTER N) as the combining mark (U+0303 COMBINING TILDE) as a whole. Reversing their order will cause the combining mark to be paired with another symbol in the string. That’s why the example output had ã
instead of ñ
.
Hopefully, this explains why all the answers posted so far are wrong.
To answer your initial question — how to [properly] reverse a string in JavaScript —, I’ve written a small JavaScript library that is capable of Unicode-aware string reversal. It doesn’t have any of the issues I just mentioned. The library is called Esrever; its code is on GitHub, and it works in pretty much any JavaScript environment. It comes with a shell utility/binary, so you can easily reverse strings from your terminal if you want.
var input = 'foo bar mañana mañana';
esrever.reverse(input);
// → 'anañam anañam rab oof'
As for the “in-place” part, see the other answers.

- 144,855
- 52
- 216
- 248
-
91You should include the main part of the code of Esrever in your answer. – r0estir0bbe Jul 31 '14 at 11:25
-
If a wrong approach used ( i.e. split().reverse().join() ) - will the length of the string always be the same after reversing? – Meglio Jan 24 '15 at 01:22
-
2
-
Hi, I checked that you are using `replace` method of string prototype which returns a new string so, its not doing it in place I think. Pls let me know if I am missing something. – vivek Feb 17 '15 at 09:44
-
-
9The problem, off-course, is that "reverse a string" sounds unambiguous, but it isn't in the face of the problems mentioned here. Is reversing a string returning the string that when printed would display the grapheme clusters in the string in reverse order? On the one hand, that sounds likely. On the other, why would you ever want to do that? This definition hinges on it being printed, and printing a reversed string is rarely useful. As part of an algorithm, your requirements might be different altogether. – Martijn Apr 14 '15 at 10:55
-
31While this does a ***great*** job of explaining the problem, the actual *answer* is [in another castle](http://meta.stackexchange.com/questions/225370/your-answer-is-in-another-castle-when-is-an-answer-not-an-answer). As @r0estir0bbe said over a year ago, the relevant code should be *in* the answer, not just linked. – T.J. Crowder Sep 17 '15 at 08:53
-
6"Hopefully, this explains why all the answers posted so far are wrong" - This assertion is overly forceful imo. Many use-cases do not require UTF-16 support (simple example; working with URL's and URL components/parameters). A solution is not "wrong" simply because it doesn't handle a non-required scenario. Notably, the top-voted answer explicitly declares that it only works with ASCII characters and thus is definitely not even a little bit wrong. – aroth Mar 07 '18 at 03:47
-
@aroth The note you refer to was addd long after this was posted. You mention “a non-required scenario” but OP doesn’t specify this limitation at all. Generally, when someone asks “how to do X?” on SO, it’s not enough to say “here’s a partial solution to the problem, in some cases” without also explaining how to solve it completely. P.S. Your use of the phrase “UTF-16 support” suggests that you’re mixing up Unicode with character encodings. – Mathias Bynens Mar 08 '18 at 06:51
-
@MathiasBynens Like most of the people who visit this page, I only see the answers as they are now. I didn't go into the edit history to see whose note came first. It's irrelevant, really. The top-voted answer explicitly disclaims support for "UTF-16 or other multi-byte characters". It's not 'wrong' for anyone who doesn't require those things. If you want to argue against partial solutions, that's fine, but then your answer is wrong too because the OP asks about reversing a string _in place_. The only 'correct' answer to that is "you can't because strings are immutable in JS". – aroth Mar 09 '18 at 11:48
-
1Again, could you post the essentials of how to reverse a string *containing strange characters* in your answer itself? – CertainPerformance Jan 12 '19 at 11:11
-
1The function is not posted *here* on Stack and the function linked is not a *reusable* function. – John Nov 01 '19 at 04:59
-
-
-
`var rxCombMark = /(<%= allExceptCombiningMarks %>)(<%= combiningMarks %>+)/g; var rxSurrPair = /([\uD800-\uDBFF])([\uDC00-\uDFFF])/g; var r = function(string) { /*combine marks & astral symbols - surrogate pairs*/ string = string /*Swap symbols w/ marks so marks go first*/ .replace(rxCombMark, function($0, $1, $2) { /*Reverse marks for reversal*/ return r($2) + $1; }) /*Swap high and low surrogates so the low go first*/ .replace(rxSurrPair, '$2$1'); /* reverse code units */ var res = []; var index = string.length; while (index--) { res.push(string.charAt(index)); } return res.join(''); };` – ruffin Jun 14 '21 at 13:19
-
^^^^^ Prettier that first, natch. :^) Let's hope the github repo doesn't go away. **NOTE:** The problem is that it uses node to set up and replace the `allExceptCombiningMarks` and `combiningMarks` values in that code. See [here for more](https://github.com/mathiasbynens/esrever/blob/14b34013dad49106ca08c0e65919f1fc8fea5331/scripts/export-data.js) -- you'd need to integrate that for vanilla JS usage. – ruffin Jun 14 '21 at 13:20
String.prototype.reverse_string=function() {return this.split("").reverse().join("");}
or
String.prototype.reverse_string = function() {
var s = "";
var i = this.length;
while (i>0) {
s += this.substring(i-1,i);
i--;
}
return s;
}
-
-
6string concatenation is expensive. Better to build an array and join it or use concat(). – Bjorn Jun 06 '09 at 05:52
-
2
-
10However, neither solution work when Unicode compound characters are present. – Eric Grange Aug 02 '11 at 09:37
-
eww, you're using the built-in functions split, reverse, join and substring. :) – Robert Aug 17 '11 at 20:42
-
use this[i] instead of substring, the asker don't want to use built-in functions :P – SparK Aug 29 '12 at 14:02
-
@BjornTipling String concatenation is not that expensive, see my performance tests here http://stackoverflow.com/questions/51185/are-javascript-strings-immutable-do-i-need-a-string-builder-in-javascript/4717855#4717855 http://jsperf.com/string-concat-without-sringbuilder/3 – Ruan Mendes Feb 25 '13 at 19:31
-
2@JuanMendes I left that comment in 2009, things have changed in the last 4 years. :P – Bjorn Feb 26 '13 at 14:48
-
@EricGrange My answer provides a Unicode-aware solution to the problem that deals with surrogate pairs and combining marks correctly: http://stackoverflow.com/a/16776380/96656 – Mathias Bynens May 27 '13 at 15:45
Detailed analysis and ten different ways to reverse a string and their performance details.
http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
Perfomance of these implementations:
Best performing implementation(s) per browser
- Chrome 15 - Implemations 1 and 6
- Firefox 7 - Implementation 6
- IE 9 - Implementation 4
- Opera 12 - Implementation 9
Here are those implementations:
Implementation 1:
function reverse(s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}
Implementation 2:
function reverse(s) {
var o = [];
for (var i = s.length - 1, j = 0; i >= 0; i--, j++)
o[j] = s[i];
return o.join('');
}
Implementation 3:
function reverse(s) {
var o = [];
for (var i = 0, len = s.length; i <= len; i++)
o.push(s.charAt(len - i));
return o.join('');
}
Implementation 4:
function reverse(s) {
return s.split('').reverse().join('');
}
Implementation 5:
function reverse(s) {
var i = s.length,
o = '';
while (i > 0) {
o += s.substring(i - 1, i);
i--;
}
return o;
}
Implementation 6:
function reverse(s) {
for (var i = s.length - 1, o = ''; i >= 0; o += s[i--]) { }
return o;
}
Implementation 7:
function reverse(s) {
return (s === '') ? '' : reverse(s.substr(1)) + s.charAt(0);
}
Implementation 8:
function reverse(s) {
function rev(s, len, o) {
return (len === 0) ? o : rev(s, --len, (o += s[len]));
};
return rev(s, s.length, '');
}
Implementation 9:
function reverse(s) {
s = s.split('');
var len = s.length,
halfIndex = Math.floor(len / 2) - 1,
tmp;
for (var i = 0; i <= halfIndex; i++) {
tmp = s[len - i - 1];
s[len - i - 1] = s[i];
s[i] = tmp;
}
return s.join('');
}
Implementation 10
function reverse(s) {
if (s.length < 2)
return s;
var halfIndex = Math.ceil(s.length / 2);
return reverse(s.substr(halfIndex)) +
reverse(s.substr(0, halfIndex));
}
Implementation 11
var reverser = function(str){
let string = str.split('');
for(i=0;i<string.length;i++){
debugger;
string.splice(i,0,string.pop());
}
console.log(string.join())
}
reverser('abcdef')
-
Why can't we just do: Array.prototype.reverse.call(string) ? like .filter works this way on strings... – RegarBoy Jul 24 '21 at 08:34
-
if you are in small project, you can do : `String.prototype.reverse = function(){ return [...this].reverse().join("")};` so you can get the reverse of string like 'reverseme'.reverse() (returned value 'emesrever') and if you want performance benefit, you can replace the prototype functions with one in this answer – rickvian Jul 31 '21 at 08:29
The whole "reverse a string in place" is an antiquated interview question C programmers, and people who were interviewed by them (for revenge, maybe?), will ask. Unfortunately, it's the "In Place" part that no longer works because strings in pretty much any managed language (JS, C#, etc) uses immutable strings, thus defeating the whole idea of moving a string without allocating any new memory.
While the solutions above do indeed reverse a string, they do not do it without allocating more memory, and thus do not satisfy the conditions. You need to have direct access to the string as allocated, and be able to manipulate its original memory location to be able to reverse it in place.
Personally, i really hate these kinds of interview questions, but sadly, i'm sure we'll keep seeing them for years to come.

- 667
- 5
- 2
-
13I can at least say that I had one interviewer a while back be pretty impressed when he asked me how to reverse a string "in-place" in JS and I explained why its impossible since strings in JS are immutable. I don't know if that was the answer he expected or if I educated him a little. Either way it worked out alright ;) – CatDadCode Jan 28 '14 at 17:43
-
1Maybe he means "managed" by a garbage collector, at least that is what is usually meant by "managed language" or the presence of a Virtual Machine / Virtual Runtime Environment? @torazaburo – AntonB Jul 15 '16 at 15:12
First, use Array.from()
to turn a string into an array, then Array.prototype.reverse()
to reverse the array, and then Array.prototype.join()
to make it back a string.
const reverse = str => Array.from(str).reverse().join('');

- 88,409
- 26
- 156
- 177
-
It's got overhead, but this is an elegant solution! There's no rewrite of the pre-existing `reverse` logic. – Gershom Maes Aug 20 '16 at 19:44
-
-
2@felixfbecker No, `string.split('')` doesn't work. See [this answer](http://stackoverflow.com/a/16776621/3853934) for more explanation. – Michał Perłakowski Oct 13 '16 at 11:40
-
5This should be the accepted answer because it also works with unicode. Eg, from the example above: `Array.from('foo bar mañana mañana').reverse().join('') == 'anãnam anañam rab oof'` – Julian TF Jan 31 '17 at 06:18
-
3@JulianTF Not exactly, one tilde is still applied to 'a' instead of 'n'. – Roman Boiko Dec 03 '17 at 14:18
-
3@RomanBoiko True, but you can normalize the string first. `Array.from('foo bar mañana mañana'.normalize('NFC')).reverse().join('')` will become `"anañam anañam rab oof"` – Mr Lister Feb 04 '20 at 13:05
-
If you can use ES6, `[...myString].reverse().join('')` works fine with Unicode. – Amsvartner Jun 28 '21 at 06:55
In ECMAScript 6, you can reverse a string even faster without using .split('')
split method, with the spread operator like so:
var str = [...'racecar'].reverse().join('');

- 1,376
- 1
- 17
- 32
-
1
-
-
3Unless you are code golfing you should avoid this. Writing `string.split('')` is clearer to most people than `[...string]`. – AnnanFay Mar 27 '18 at 01:06
-
6@AnnanFay `.split('')` has the issue with characters from the supplementary planes (surrogate pairs in UTF-16), because it splits by UTF-16 code *unit* rather than code *point*. The spread operator and `Array.from()` (my preference) don't. – Inkling Feb 16 '20 at 04:23
-
@Inkling I didn't realise that was an issue. Thanks for pointing it out. I'd still be tempted to write a utility function for clarity. – AnnanFay Feb 16 '20 at 20:53
-
Seems like I'm 3 years late to the party...
Unfortunately you can't as has been pointed out. See Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?
The next best thing you can do is to create a "view" or "wrapper", which takes a string and reimplements whatever parts of the string API you are using, but pretending the string is reversed. For example:
var identity = function(x){return x};
function LazyString(s) {
this.original = s;
this.length = s.length;
this.start = 0; this.stop = this.length; this.dir = 1; // "virtual" slicing
// (dir=-1 if reversed)
this._caseTransform = identity;
}
// syntactic sugar to create new object:
function S(s) {
return new LazyString(s);
}
//We now implement a `"...".reversed` which toggles a flag which will change our math:
(function(){ // begin anonymous scope
var x = LazyString.prototype;
// Addition to the String API
x.reversed = function() {
var s = new LazyString(this.original);
s.start = this.stop - this.dir;
s.stop = this.start - this.dir;
s.dir = -1*this.dir;
s.length = this.length;
s._caseTransform = this._caseTransform;
return s;
}
//We also override string coercion for some extra versatility (not really necessary):
// OVERRIDE STRING COERCION
// - for string concatenation e.g. "abc"+reversed("abc")
x.toString = function() {
if (typeof this._realized == 'undefined') { // cached, to avoid recalculation
this._realized = this.dir==1 ?
this.original.slice(this.start,this.stop) :
this.original.slice(this.stop+1,this.start+1).split("").reverse().join("");
this._realized = this._caseTransform.call(this._realized, this._realized);
}
return this._realized;
}
//Now we reimplement the String API by doing some math:
// String API:
// Do some math to figure out which character we really want
x.charAt = function(i) {
return this.slice(i, i+1).toString();
}
x.charCodeAt = function(i) {
return this.slice(i, i+1).toString().charCodeAt(0);
}
// Slicing functions:
x.slice = function(start,stop) {
// lazy chaining version of https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice
if (stop===undefined)
stop = this.length;
var relativeStart = start<0 ? this.length+start : start;
var relativeStop = stop<0 ? this.length+stop : stop;
if (relativeStart >= this.length)
relativeStart = this.length;
if (relativeStart < 0)
relativeStart = 0;
if (relativeStop > this.length)
relativeStop = this.length;
if (relativeStop < 0)
relativeStop = 0;
if (relativeStop < relativeStart)
relativeStop = relativeStart;
var s = new LazyString(this.original);
s.length = relativeStop - relativeStart;
s.start = this.start + this.dir*relativeStart;
s.stop = s.start + this.dir*s.length;
s.dir = this.dir;
//console.log([this.start,this.stop,this.dir,this.length], [s.start,s.stop,s.dir,s.length])
s._caseTransform = this._caseTransform;
return s;
}
x.substring = function() {
// ...
}
x.substr = function() {
// ...
}
//Miscellaneous functions:
// Iterative search
x.indexOf = function(value) {
for(var i=0; i<this.length; i++)
if (value==this.charAt(i))
return i;
return -1;
}
x.lastIndexOf = function() {
for(var i=this.length-1; i>=0; i--)
if (value==this.charAt(i))
return i;
return -1;
}
// The following functions are too complicated to reimplement easily.
// Instead just realize the slice and do it the usual non-in-place way.
x.match = function() {
var s = this.toString();
return s.apply(s, arguments);
}
x.replace = function() {
var s = this.toString();
return s.apply(s, arguments);
}
x.search = function() {
var s = this.toString();
return s.apply(s, arguments);
}
x.split = function() {
var s = this.toString();
return s.apply(s, arguments);
}
// Case transforms:
x.toLowerCase = function() {
var s = new LazyString(this.original);
s._caseTransform = ''.toLowerCase;
s.start=this.start; s.stop=this.stop; s.dir=this.dir; s.length=this.length;
return s;
}
x.toUpperCase = function() {
var s = new LazyString(this.original);
s._caseTransform = ''.toUpperCase;
s.start=this.start; s.stop=this.stop; s.dir=this.dir; s.length=this.length;
return s;
}
})() // end anonymous scope
Demo:
> r = S('abcABC')
LazyString
original: "abcABC"
__proto__: LazyString
> r.charAt(1); // doesn't reverse string!!! (good if very long)
"B"
> r.toLowerCase() // must reverse string, so does so
"cbacba"
> r.toUpperCase() // string already reversed: no extra work
"CBACBA"
> r + '-demo-' + r // natural coercion, string already reversed: no extra work
"CBAcba-demo-CBAcba"
The kicker -- the following is done in-place by pure math, visiting each character only once, and only if necessary:
> 'demo: ' + S('0123456789abcdef').slice(3).reversed().slice(1,-1).toUpperCase()
"demo: EDCBA987654"
> S('0123456789ABCDEF').slice(3).reversed().slice(1,-1).toLowerCase().charAt(3)
"b"
This yields significant savings if applied to a very large string, if you are only taking a relatively small slice thereof.
Whether this is worth it (over reversing-as-a-copy like in most programming languages) highly depends on your use case and how efficiently you reimplement the string API. For example if all you want is to do string index manipulation, or take small slice
s or substr
s, this will save you space and time. If you're planning on printing large reversed slices or substrings however, the savings may be small indeed, even worse than having done a full copy. Your "reversed" string will also not have the type string
, though you might be able to fake this with prototyping.
The above demo implementation creates a new object of type ReversedString. It is prototyped, and therefore fairly efficient, with almost minimal work and minimal space overhead (prototype definitions are shared). It is a lazy implementation involving deferred slicing. Whenever you perform a function like .slice
or .reversed
, it will perform index mathematics. Finally when you extract data (by implicitly calling .toString()
or .charCodeAt(...)
or something), it will apply those in a "smart" manner, touching the least data possible.
Note: the above string API is an example, and may not be implemented perfectly. You also can use just 1-2 functions which you need.

- 1
- 1

- 88,546
- 24
- 137
- 145
Legible way using spread syntax:
const reverseString = str => [...str].reverse().join('');
console.log(reverseString('ABC'));

- 45,728
- 6
- 46
- 64

- 448
- 6
- 19
There are many ways you can reverse a string in JavaScript. I'm jotting down three ways I prefer.
Approach 1: Using reverse function:
function reverse(str) {
return str.split('').reverse().join('');
}
Approach 2: Looping through characters:
function reverse(str) {
let reversed = '';
for (let character of str) {
reversed = character + reversed;
}
return reversed;
}
Approach 3: Using reduce function:
function reverse(str) {
return str.split('').reduce((rev, char) => char + rev, '');
}
I hope this helps :)

- 441
- 4
- 5
There are Multiple ways of doing it, you may check the following,
1. Traditional for loop(incrementing):
function reverseString(str){
let stringRev ="";
for(let i= 0; i<str.length; i++){
stringRev = str[i]+stringRev;
}
return stringRev;
}
alert(reverseString("Hello World!"));
2. Traditional for loop(decrementing):
function reverseString(str){
let revstr = "";
for(let i = str.length-1; i>=0; i--){
revstr = revstr+ str[i];
}
return revstr;
}
alert(reverseString("Hello World!"));
3. Using for-of loop
function reverseString(str){
let strn ="";
for(let char of str){
strn = char + strn;
}
return strn;
}
alert(reverseString("Get well soon"));
4. Using the forEach/ high order array method:
function reverseString(str){
let revSrring = "";
str.split("").forEach(function(char){
revSrring = char + revSrring;
});
return revSrring;
}
alert(reverseString("Learning JavaScript"));
5. ES6 standard:
function reverseString(str){
let revSrring = "";
str.split("").forEach(char => revSrring = char + revSrring);
return revSrring;
}
alert(reverseString("Learning JavaScript"));
6. The latest way:
function reverseString(str){
return str.split("").reduce(function(revString, char){
return char + revString;
}, "");
}
alert(reverseString("Learning JavaScript"));
7. You may also get the result using the following,
function reverseString(str){
return str.split("").reduce((revString, char)=> char + revString, "");
}
alert(reverseString("Learning JavaScript"));

- 192
- 1
- 10
During an interview, I was asked to reverse a string without using any variables or native methods. This is my favorite implementation:
function reverseString(str) {
return str === '' ? '' : reverseString(str.slice(1)) + str[0];
}

- 616
- 7
- 10
-
-
15
-
1Interesting use of recursion. Ironic that it's on Stack Overflow. http://stackoverflow.com/q/2805172/265877 – Alex Sep 02 '15 at 17:17
-
@Alex, you make a good point. In some cases, the interviewer will ask you not to use `Array.prototype.reverse()`. – Daniel Oct 01 '18 at 19:02
In ES6, you have one more option
function reverseString (str) {
return [...str].reverse().join('')
}
reverseString('Hello');

- 238
- 3
- 6
var str = 'sample string';
[].map.call(str, function(x) {
return x;
}).reverse().join('');
OR
var str = 'sample string';
console.log(str.split('').reverse().join(''));
// Output: 'gnirts elpmas'

- 125
- 1
- 2
- 6
If you don't want to use any built in function. Try this
var string = 'abcdefg';
var newstring = '';
for(let i = 0; i < string.length; i++){
newstring = string[i] += newstring;
}
console.log(newstring);

- 20,879
- 9
- 40
- 61

- 612
- 10
- 15
This is the easiest way I think
var reverse = function(str) {
var arr = [];
for (var i = 0, len = str.length; i <= len; i++) {
arr.push(str.charAt(len - i))
}
return arr.join('');
}
console.log(reverse('I want a '));

- 28,690
- 9
- 51
- 58
-
5It's nice that you've included an emoji in your example. So that we quickly see that this clearly doesn't work for emojis and a lot of other unicode chars. – Íhor Mé Jul 21 '17 at 20:48
-
Faith, while your answer is correct, I disagree that it is the easiest way. The first several answers make use of `Array.prototype.reverse()` that would be the easiest way, hence the most popular answer. Of course, it would require good prior knowledge of JavaScript. – Daniel Oct 01 '18 at 19:04
I know that this is an old question that has been well answered, but for my own amusement I wrote the following reverse function and thought I would share it in case it was useful for anyone else. It handles both surrogate pairs and combining marks:
function StringReverse (str)
{
var charArray = [];
for (var i = 0; i < str.length; i++)
{
if (i+1 < str.length)
{
var value = str.charCodeAt(i);
var nextValue = str.charCodeAt(i+1);
if ( ( value >= 0xD800 && value <= 0xDBFF
&& (nextValue & 0xFC00) == 0xDC00) // Surrogate pair)
|| (nextValue >= 0x0300 && nextValue <= 0x036F)) // Combining marks
{
charArray.unshift(str.substring(i, i+2));
i++; // Skip the other half
continue;
}
}
// Otherwise we just have a rogue surrogate marker or a plain old character.
charArray.unshift(str[i]);
}
return charArray.join('');
}
All props to Mathias, Punycode, and various other references for schooling me on the complexities of character encoding in JavaScript.

- 862
- 14
- 22
You can't because JS strings are immutable. Short non-in-place solution
[...str].reverse().join``
let str = "Hello World!";
let r = [...str].reverse().join``;
console.log(r);

- 85,173
- 29
- 368
- 345
As other's have pointed out, strings are immutable, so you cannot reverse it in-place. You'll need to produce a new string instead. One new option to do this is to use Intl.Segmenter which allows you to split on the visual graphemes (ie: user-perceived character units such as emojis, characters, etc.). Intl.Segmenter
is currently a stage 4 proposal and there is a polyfill available for it if you wish to use it. It currently has limited browser support which you can find more information about here.
Here is how the reverse()
method may look if you use Intl.Segmenter
:
const reverse = str => {
const segmenter = new Intl.Segmenter("en", {granularity: 'grapheme'});
const segitr = segmenter.segment(str);
const segarr = Array.from(segitr, ({segment}) => segment).reverse();
return segarr.join('');
}
console.log(reverse('foo bar mañana mañana')); // anañam anañam rab oof
console.log(reverse('This emoji is happy')); // yppah si ijome sihT
console.log(reverse('Text surrogate pair composite pair möo varient selector ❤️ & ZWJ ')); // JWZ & ❤️ rotceles tneirav oöm riap etisopmoc riap etagorrus txeT
The above creates a segmenter
to segment/split strings by their visual graphemes. Calling .segment()
on the segmenter
with the string input then returns an iterator, which produces objects of the form {segment, index, input, isWordLike}
. The segment
key from this object contains the string segment (ie: the individual grapheme). To convert the iterator to an array, we use Array.from()
on the iterator and extract the segmented graphemes, which can be reversed with .reverse()
. Lastly, we join the array back into a string using .join()
There is also another option which you can try that has better browser support than Intl.Segmenter, however isn't as bullet-proof:
const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');
this helps deal with characters consisting of multiple code points and code units. As pointed out in other answers, there are issues with maintaining composite and surrogate pair ordering in strings such as 'foo bar mañana mañana'
. Here is a surrogate pair consisting of two code units, and the last
ñ
is a composite pair consisting of two Unicode characters to make up one grapheme (n
+̃
= ñ
).
In order to reverse each character, you can use the .reverse()
method which is part of the Array prototype. As .reverse()
is used on an array, the first thing to do is to turn the string into an array of characters. Typically, .split('')
is used for this task, however, this splits up surrogate pairs which are made from up of multiple code units (as already shown in previous answers):
>> ''.split('')
>> `["�", "�"]`
Instead, if you invoke the String.prototype
's Symbol.iterator method then you'll be able to retain your surrogate pairs within your array, as this iterates over the code points rather than the code units of your string:
>> [...'']
>> [""]
The next thing to handle is any composite characters within the string. Characters that consist of two or more code points will still be split when iterated on:
>> [...'ö']
>> ["o", "̈"]
The above separates the base character (o) from the diaresis, which is not desired behavior. This is because ö
is a decomposed version of the character, consisting of multiple code points. To deal with this, you can use a string method introduced in ES6 known as String.prototype.normalize()
. This method can compose multiple code points into its composed canonical form by using "NFC" as an argument. This allows us to convert the decomposed character ö
(o + combining diaeresis) into its precomposed form ö
(latin small letter o with diaeresis) which consists of only one code point. Calling .normalize()
with "NFC"
thus tries to replace multiple code points with single code points where possible. This allows graphemes consisting of two code points to be represented with one code point.
>> [...'ö'.normalize('NFC')]
>> ["ö"]
As normalize('NFC')
produces one character, it can then be reversed safely when amongst others. Putting both the spread syntax and normalization together, you can successfully reverse strings of characters such as:
const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');
console.log(reverse('foo bar mañana mañana'));
console.log(reverse('This emoji is happy'));
There are a few cases where the above normalization+iteration will fail. For instance, the character ❤️ (heavy black heart ❤️
) consists of two code points. The first being the heart and the latter being the variation selector-16 (U+FE0F) which is used to define a glyph variant for the preceding character. Other characters can also produce similar issues like this.
Another thing to look out for is ZWJ (Zero-width joiner) characters, which you can find in some scripts, including emoji. For example the emoji comprises of the Man, Woman and Boy emoji, each separated by a ZWJ. The above normalization + iteration method will not account for this either.
As a result, using Intl.Segmenter
is the better choice over these two approaches. Currently, Chrome also has its own specific segmentation API known as Intl.v8BreakIterator. This segmentation API is nonstandard and something that Chrome simply just implements. So, it is subject to change and doesn't work on most browsers, so it's not recommended to use. However, if you're curious, this is how it could be done:
const reverse = str => {
const iterator = Intl.v8BreakIterator(['en'], {type: 'character'});
iterator.adoptText(str);
const arr = [];
let pos = iterator.first();
while (pos !== -1) {
const current = iterator.current();
const nextPos = iterator.next();
if (nextPos === -1) break;
const slice = str.slice(current, nextPos);
arr.unshift(slice);
}
return arr.join("");
}
console.log(reverse('foo bar mañana mañana')); // anañam anañam rab oof
console.log(reverse('This emoji is happy')); // yppah si ijome sihT
console.log(reverse('Text surrogate pair composite pair möo varient selector ❤️ & ZWJ ')); // JWZ & ❤️ rotceles tneirav oöm riap etisopmoc riap etagorrus txeT

- 45,728
- 6
- 46
- 64
You can't reverse a string
in place but you can use this:
String.prototype.reverse = function() {
return this.split("").reverse().join("");
}
var s = "ABCD";
s = s.reverse();
console.log(s);

- 1,322
- 1
- 16
- 21
-
I think `return [...str].reduce((rev, currentChar) => currentChar + rev, '');` is better as it works on emojis (or any multi byte char). Otherwise `reverse("abc") = "c\udf88\ud83cba" ` and not `"cba"` – YoniXw Jun 27 '21 at 18:53
UTF-8 strings can have:
- Combining diacritics such as
b̃
which composed of theb
character and a following~
diacritic generated by the unicode escape sequnce\u0303
; - Multi-byte characters such as
; which is generated by the multi-byte unicode escape sequence
\uD83C\uDFA5
; and - Multiple characters may be combined together with a zero-width joiner character (given by the unicode escape sequence
\u200D
). For example, the character
can be composed using the individual (multi-byte) emojis then a zero-width joiner then then another zero-width joiner then such that the entire 3-person character is 8-bytes (\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66
).
This will handle reversing all 3 cases and keeping the bytes in the correct order such that the characters are reversed (rather than naively reversing the bytes of the string):
(function(){
var isCombiningDiacritic = function( code )
{
return (0x0300 <= code && code <= 0x036F) // Comb. Diacritical Marks
|| (0x1AB0 <= code && code <= 0x1AFF) // Comb. Diacritical Marks Extended
|| (0x1DC0 <= code && code <= 0x1DFF) // Comb. Diacritical Marks Supplement
|| (0x20D0 <= code && code <= 0x20FF) // Comb. Diacritical Marks for Symbols
|| (0xFE20 <= code && code <= 0xFE2F); // Comb. Half Marks
};
String.prototype.reverse = function()
{
let output = "";
for ( let i = this.length; i > 0; )
{
let width = 0;
let has_zero_width_joiner = false;
while( i > 0 && isCombiningDiacritic( this.charCodeAt(i-1) ) )
{
--i;
width++;
}
do {
--i;
width++;
if (
i > 0
&& "\uDC00" <= this[i] && this[i] <= "\uDFFF"
&& "\uD800" <= this[i-1] && this[i-1] <= "\uDBFF"
)
{
--i;
width++;
}
has_zero_width_joiner = i > 0 && "\u200D" == this[i-1];
if ( has_zero_width_joiner )
{
--i;
width++;
}
}
while( i > 0 && has_zero_width_joiner );
output += this.substr( i, width );
}
return output;
}
})();
// Tests
[
'abcdefg',
'ab\u0303c',
'a\uD83C\uDFA5b',
'a\uD83C\uDFA5b\uD83C\uDFA6c',
'a\uD83C\uDFA5b\u0306c\uD83C\uDFA6d',
'TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚N̐Y̡', // copied from http://stackoverflow.com/a/1732454/1509264
'What is this?'
].forEach(
function(str){ console.log( str + " -> " + str.reverse() ); }
);
Update
The above code identifies some of the more commonly used combining diacritics. A more complete list of combining diacritics (that could be swapped into the above code) is:
var isCombiningDiacritic = function( code )
{
return (0x0300 <= code && code <= 0x036F)
|| (0x0483 <= code && code <= 0x0489)
|| (0x0591 <= code && code <= 0x05BD)
|| (code == 0x05BF)
|| (0x05C1 <= code && code <= 0x05C2)
|| (0x05C4 <= code && code <= 0x05C5)
|| (code == 0x05C7)
|| (0x0610 <= code && code <= 0x061A)
|| (0x064B <= code && code <= 0x065F)
|| (code == 0x0670)
|| (0x06D6 <= code && code <= 0x06DC)
|| (0x06DF <= code && code <= 0x06E4)
|| (0x06E7 <= code && code <= 0x06E8)
|| (0x06EA <= code && code <= 0x06ED)
|| (code == 0x0711)
|| (0x0730 <= code && code <= 0x074A)
|| (0x07A6 <= code && code <= 0x07B0)
|| (0x07EB <= code && code <= 0x07F3)
|| (code == 0x07FD)
|| (0x0816 <= code && code <= 0x0819)
|| (0x081B <= code && code <= 0x0823)
|| (0x0825 <= code && code <= 0x0827)
|| (0x0829 <= code && code <= 0x082D)
|| (0x0859 <= code && code <= 0x085B)
|| (0x08D3 <= code && code <= 0x08E1)
|| (0x08E3 <= code && code <= 0x0902)
|| (code == 0x093A)
|| (code == 0x093C)
|| (0x0941 <= code && code <= 0x0948)
|| (code == 0x094D)
|| (0x0951 <= code && code <= 0x0957)
|| (0x0962 <= code && code <= 0x0963)
|| (code == 0x0981)
|| (code == 0x09BC)
|| (0x09C1 <= code && code <= 0x09C4)
|| (code == 0x09CD)
|| (0x09E2 <= code && code <= 0x09E3)
|| (0x09FE <= code && code <= 0x0A02)
|| (code == 0x0A3C)
|| (0x0A41 <= code && code <= 0x0A51)
|| (0x0A70 <= code && code <= 0x0A71)
|| (code == 0x0A75)
|| (0x0A81 <= code && code <= 0x0A82)
|| (code == 0x0ABC)
|| (0x0AC1 <= code && code <= 0x0AC8)
|| (code == 0x0ACD)
|| (0x0AE2 <= code && code <= 0x0AE3)
|| (0x0AFA <= code && code <= 0x0B01)
|| (code == 0x0B3C)
|| (code == 0x0B3F)
|| (0x0B41 <= code && code <= 0x0B44)
|| (0x0B4D <= code && code <= 0x0B56)
|| (0x0B62 <= code && code <= 0x0B63)
|| (code == 0x0B82)
|| (code == 0x0BC0)
|| (code == 0x0BCD)
|| (code == 0x0C00)
|| (code == 0x0C04)
|| (0x0C3E <= code && code <= 0x0C40)
|| (0x0C46 <= code && code <= 0x0C56)
|| (0x0C62 <= code && code <= 0x0C63)
|| (code == 0x0C81)
|| (code == 0x0CBC)
|| (0x0CCC <= code && code <= 0x0CCD)
|| (0x0CE2 <= code && code <= 0x0CE3)
|| (0x0D00 <= code && code <= 0x0D01)
|| (0x0D3B <= code && code <= 0x0D3C)
|| (0x0D41 <= code && code <= 0x0D44)
|| (code == 0x0D4D)
|| (0x0D62 <= code && code <= 0x0D63)
|| (code == 0x0DCA)
|| (0x0DD2 <= code && code <= 0x0DD6)
|| (code == 0x0E31)
|| (0x0E34 <= code && code <= 0x0E3A)
|| (0x0E47 <= code && code <= 0x0E4E)
|| (code == 0x0EB1)
|| (0x0EB4 <= code && code <= 0x0EBC)
|| (0x0EC8 <= code && code <= 0x0ECD)
|| (0x0F18 <= code && code <= 0x0F19)
|| (code == 0x0F35)
|| (code == 0x0F37)
|| (code == 0x0F39)
|| (0x0F71 <= code && code <= 0x0F7E)
|| (0x0F80 <= code && code <= 0x0F84)
|| (0x0F86 <= code && code <= 0x0F87)
|| (0x0F8D <= code && code <= 0x0FBC)
|| (code == 0x0FC6)
|| (0x102D <= code && code <= 0x1030)
|| (0x1032 <= code && code <= 0x1037)
|| (0x1039 <= code && code <= 0x103A)
|| (0x103D <= code && code <= 0x103E)
|| (0x1058 <= code && code <= 0x1059)
|| (0x105E <= code && code <= 0x1060)
|| (0x1071 <= code && code <= 0x1074)
|| (code == 0x1082)
|| (0x1085 <= code && code <= 0x1086)
|| (code == 0x108D)
|| (code == 0x109D)
|| (0x135D <= code && code <= 0x135F)
|| (0x1712 <= code && code <= 0x1714)
|| (0x1732 <= code && code <= 0x1734)
|| (0x1752 <= code && code <= 0x1753)
|| (0x1772 <= code && code <= 0x1773)
|| (0x17B4 <= code && code <= 0x17B5)
|| (0x17B7 <= code && code <= 0x17BD)
|| (code == 0x17C6)
|| (0x17C9 <= code && code <= 0x17D3)
|| (code == 0x17DD)
|| (0x180B <= code && code <= 0x180D)
|| (0x1885 <= code && code <= 0x1886)
|| (code == 0x18A9)
|| (0x1920 <= code && code <= 0x1922)
|| (0x1927 <= code && code <= 0x1928)
|| (code == 0x1932)
|| (0x1939 <= code && code <= 0x193B)
|| (0x1A17 <= code && code <= 0x1A18)
|| (code == 0x1A1B)
|| (code == 0x1A56)
|| (0x1A58 <= code && code <= 0x1A60)
|| (code == 0x1A62)
|| (0x1A65 <= code && code <= 0x1A6C)
|| (0x1A73 <= code && code <= 0x1A7F)
|| (0x1AB0 <= code && code <= 0x1B03)
|| (code == 0x1B34)
|| (0x1B36 <= code && code <= 0x1B3A)
|| (code == 0x1B3C)
|| (code == 0x1B42)
|| (0x1B6B <= code && code <= 0x1B73)
|| (0x1B80 <= code && code <= 0x1B81)
|| (0x1BA2 <= code && code <= 0x1BA5)
|| (0x1BA8 <= code && code <= 0x1BA9)
|| (0x1BAB <= code && code <= 0x1BAD)
|| (code == 0x1BE6)
|| (0x1BE8 <= code && code <= 0x1BE9)
|| (code == 0x1BED)
|| (0x1BEF <= code && code <= 0x1BF1)
|| (0x1C2C <= code && code <= 0x1C33)
|| (0x1C36 <= code && code <= 0x1C37)
|| (0x1CD0 <= code && code <= 0x1CD2)
|| (0x1CD4 <= code && code <= 0x1CE0)
|| (0x1CE2 <= code && code <= 0x1CE8)
|| (code == 0x1CED)
|| (code == 0x1CF4)
|| (0x1CF8 <= code && code <= 0x1CF9)
|| (0x1DC0 <= code && code <= 0x1DFF)
|| (0x20D0 <= code && code <= 0x20F0)
|| (0x2CEF <= code && code <= 0x2CF1)
|| (code == 0x2D7F)
|| (0x2DE0 <= code && code <= 0x2DFF)
|| (0x302A <= code && code <= 0x302D)
|| (0x3099 <= code && code <= 0x309A)
|| (0xA66F <= code && code <= 0xA672)
|| (0xA674 <= code && code <= 0xA67D)
|| (0xA69E <= code && code <= 0xA69F)
|| (0xA6F0 <= code && code <= 0xA6F1)
|| (code == 0xA802)
|| (code == 0xA806)
|| (code == 0xA80B)
|| (0xA825 <= code && code <= 0xA826)
|| (0xA8C4 <= code && code <= 0xA8C5)
|| (0xA8E0 <= code && code <= 0xA8F1)
|| (code == 0xA8FF)
|| (0xA926 <= code && code <= 0xA92D)
|| (0xA947 <= code && code <= 0xA951)
|| (0xA980 <= code && code <= 0xA982)
|| (code == 0xA9B3)
|| (0xA9B6 <= code && code <= 0xA9B9)
|| (0xA9BC <= code && code <= 0xA9BD)
|| (code == 0xA9E5)
|| (0xAA29 <= code && code <= 0xAA2E)
|| (0xAA31 <= code && code <= 0xAA32)
|| (0xAA35 <= code && code <= 0xAA36)
|| (code == 0xAA43)
|| (code == 0xAA4C)
|| (code == 0xAA7C)
|| (code == 0xAAB0)
|| (0xAAB2 <= code && code <= 0xAAB4)
|| (0xAAB7 <= code && code <= 0xAAB8)
|| (0xAABE <= code && code <= 0xAABF)
|| (code == 0xAAC1)
|| (0xAAEC <= code && code <= 0xAAED)
|| (code == 0xAAF6)
|| (code == 0xABE5)
|| (code == 0xABE8)
|| (code == 0xABED)
|| (code == 0xFB1E)
|| (0xFE00 <= code && code <= 0xFE0F)
|| (0xFE20 <= code && code <= 0xFE2F)
|| (code == 0x101FD)
|| (code == 0x102E0)
|| (0x10376 <= code && code <= 0x1037A)
|| (0x10A01 <= code && code <= 0x10A0F)
|| (0x10A38 <= code && code <= 0x10A3F)
|| (0x10AE5 <= code && code <= 0x10AE6)
|| (0x10D24 <= code && code <= 0x10D27)
|| (0x10F46 <= code && code <= 0x10F50)
|| (code == 0x11001)
|| (0x11038 <= code && code <= 0x11046)
|| (0x1107F <= code && code <= 0x11081)
|| (0x110B3 <= code && code <= 0x110B6)
|| (0x110B9 <= code && code <= 0x110BA)
|| (0x11100 <= code && code <= 0x11102)
|| (0x11127 <= code && code <= 0x1112B)
|| (0x1112D <= code && code <= 0x11134)
|| (code == 0x11173)
|| (0x11180 <= code && code <= 0x11181)
|| (0x111B6 <= code && code <= 0x111BE)
|| (0x111C9 <= code && code <= 0x111CC)
|| (0x1122F <= code && code <= 0x11231)
|| (code == 0x11234)
|| (0x11236 <= code && code <= 0x11237)
|| (code == 0x1123E)
|| (code == 0x112DF)
|| (0x112E3 <= code && code <= 0x112EA)
|| (0x11300 <= code && code <= 0x11301)
|| (0x1133B <= code && code <= 0x1133C)
|| (code == 0x11340)
|| (0x11366 <= code && code <= 0x11374)
|| (0x11438 <= code && code <= 0x1143F)
|| (0x11442 <= code && code <= 0x11444)
|| (code == 0x11446)
|| (code == 0x1145E)
|| (0x114B3 <= code && code <= 0x114B8)
|| (code == 0x114BA)
|| (0x114BF <= code && code <= 0x114C0)
|| (0x114C2 <= code && code <= 0x114C3)
|| (0x115B2 <= code && code <= 0x115B5)
|| (0x115BC <= code && code <= 0x115BD)
|| (0x115BF <= code && code <= 0x115C0)
|| (0x115DC <= code && code <= 0x115DD)
|| (0x11633 <= code && code <= 0x1163A)
|| (code == 0x1163D)
|| (0x1163F <= code && code <= 0x11640)
|| (code == 0x116AB)
|| (code == 0x116AD)
|| (0x116B0 <= code && code <= 0x116B5)
|| (code == 0x116B7)
|| (0x1171D <= code && code <= 0x1171F)
|| (0x11722 <= code && code <= 0x11725)
|| (0x11727 <= code && code <= 0x1172B)
|| (0x1182F <= code && code <= 0x11837)
|| (0x11839 <= code && code <= 0x1183A)
|| (0x119D4 <= code && code <= 0x119DB)
|| (code == 0x119E0)
|| (0x11A01 <= code && code <= 0x11A06)
|| (0x11A09 <= code && code <= 0x11A0A)
|| (0x11A33 <= code && code <= 0x11A38)
|| (0x11A3B <= code && code <= 0x11A3E)
|| (code == 0x11A47)
|| (0x11A51 <= code && code <= 0x11A56)
|| (0x11A59 <= code && code <= 0x11A5B)
|| (0x11A8A <= code && code <= 0x11A96)
|| (0x11A98 <= code && code <= 0x11A99)
|| (0x11C30 <= code && code <= 0x11C3D)
|| (0x11C92 <= code && code <= 0x11CA7)
|| (0x11CAA <= code && code <= 0x11CB0)
|| (0x11CB2 <= code && code <= 0x11CB3)
|| (0x11CB5 <= code && code <= 0x11CB6)
|| (0x11D31 <= code && code <= 0x11D45)
|| (code == 0x11D47)
|| (0x11D90 <= code && code <= 0x11D91)
|| (code == 0x11D95)
|| (code == 0x11D97)
|| (0x11EF3 <= code && code <= 0x11EF4)
|| (0x16AF0 <= code && code <= 0x16AF4)
|| (0x16B30 <= code && code <= 0x16B36)
|| (code == 0x16F4F)
|| (0x16F8F <= code && code <= 0x16F92)
|| (0x1BC9D <= code && code <= 0x1BC9E)
|| (0x1D167 <= code && code <= 0x1D169)
|| (0x1D17B <= code && code <= 0x1D182)
|| (0x1D185 <= code && code <= 0x1D18B)
|| (0x1D1AA <= code && code <= 0x1D1AD)
|| (0x1D242 <= code && code <= 0x1D244)
|| (0x1DA00 <= code && code <= 0x1DA36)
|| (0x1DA3B <= code && code <= 0x1DA6C)
|| (code == 0x1DA75)
|| (code == 0x1DA84)
|| (0x1DA9B <= code && code <= 0x1E02A)
|| (0x1E130 <= code && code <= 0x1E136)
|| (0x1E2EC <= code && code <= 0x1E2EF)
|| (0x1E8D0 <= code && code <= 0x1E8D6)
|| (0x1E944 <= code && code <= 0x1E94A)
|| (0xE0100 <= code && code <= 0xE01EF);
};

- 143,790
- 11
- 59
- 117
The real answer is: you can't reverse it in place, but you can create a new string that is the reverse.
Just as an exercise to play with recursion: sometimes when you go to an interview, the interviewer may ask you how to do this using recursion, and I think the "preferred answer" might be "I would rather not do this in recursion as it can easily cause a stack overflow" (because it is O(n)
rather than O(log n)
. If it is O(log n)
, it is quite difficult to get a stack overflow -- 4 billion items could be handled by a stack level of 32, as 2 ** 32 is 4294967296. But if it is O(n)
, then it can easily get a stack overflow.
Sometimes the interviewer will still ask you, "just as an exercise, why don't you still write it using recursion?" And here it is:
String.prototype.reverse = function() {
if (this.length <= 1) return this;
else return this.slice(1).reverse() + this.slice(0,1);
}
test run:
var s = "";
for(var i = 0; i < 1000; i++) {
s += ("apple" + i);
}
console.log(s.reverse());
output:
999elppa899elppa...2elppa1elppa0elppa
To try getting a stack overflow, I changed 1000
to 10000
in Google Chrome, and it reported:
RangeError: Maximum call stack size exceeded

- 146,324
- 131
- 460
- 740
I think String.prototype.reverse is a good way to solve this problem; the code as below;
String.prototype.reverse = function() {
return this.split('').reverse().join('');
}
var str = 'this is a good example for string reverse';
str.reverse();
-> "esrever gnirts rof elpmaxe doog a si siht";

- 636
- 5
- 9
Strings themselves are immutable, but you can easily create a reversed copy with the following code:
function reverseString(str) {
var strArray = str.split("");
strArray.reverse();
var strReverse = strArray.join("");
return strReverse;
}
reverseString("hello");

- 1,053
- 15
- 21
//es6
//array.from
const reverseString = (string) => Array.from(string).reduce((a, e) => e + a);
//split
const reverseString = (string) => string.split('').reduce((a, e) => e + a);
//split problem
"".split('')[0] === Array.from("")[0] // "�" === "" => false
"".split('')[0] === Array.from("")[0] // "�" === "" => false

- 2,799
- 1
- 17
- 25
-
1This has the advantage that it handles supplementary plane characters correctly. – May 01 '17 at 05:16
Reverse a String using built-in functions
function reverse(str) {
// Use the split() method to return a new array
// Use the reverse() method to reverse the new created array
// Use the join() method to join all elements of the array into a string
return str.split("").reverse().join("");
}
console.log(reverse('hello'));
Reverse a String without the helpers
function reversedOf(str) {
let newStr = '';
for (let char of str) {
newStr = char + newStr
// 1st round: "h" + "" = h, 2nd round: "e" + "h" = "eh" ... etc.
// console.log(newStr);
}
return newStr;
}
console.log(reversedOf('hello'));

- 7,284
- 3
- 25
- 44
-
[how to reverse string in js](https://www.youtube.com/watch?v=j_zyN0aPoGU) – InfiniteStack Jun 06 '22 at 15:34
function reverseString(string) {
var reversedString = "";
var stringLength = string.length - 1;
for (var i = stringLength; i >= 0; i--) {
reversedString += string[i];
}
return reversedString;
}
Using Array functions,
String.prototype.reverse = function(){
return [].reduceRight.call(this, function(last, secLast){return last + secLast});
}

- 750
- 7
- 19
var str = "my name is saurabh ";
var empStr='',finalString='';
var chunk=[];
function reverse(str){
var i,j=0,n=str.length;
for(i=0;i<n;++i){
if(str[i]===' '){
chunk[j]=empStr;
empStr = '';
j++;
}else{
empStr=empStr+str[i];
}
}
for(var z=chunk.length-1;z>=0;z--){
finalString = finalString +' '+ chunk[z];
console.log(finalString);
}
return true;
}
reverse(str);

- 41
- 6
Here's a basic ES6 immutable example without using Array.prototype.reverse:
// :: reverse = String -> String
const reverse = s => [].reduceRight.call(s, (a, b) => a + b)
console.log(reverse('foo')) // => 'oof'
console.log(reverse('bar')) // => 'rab'
console.log(reverse('foo-bar')) // => 'rab-oof'

- 1,735
- 1
- 15
- 19
-
Providing an explanation on how your solution resolves the problem will help your readers learn. – ivan.sim Jun 12 '15 at 01:40
My own original attempt...
var str = "The Car";
function reverseStr(str) {
var reversed = "";
var len = str.length;
for (var i = 1; i < (len + 1); i++) {
reversed += str[len - i];
}
return reversed;
}
var strReverse = reverseStr(str);
console.log(strReverse);
// "raC ehT"

- 2,724
- 1
- 31
- 39
Keep it DRY and simple silly!!
function reverse(s){
let str = s;
var reverse = '';
for (var i=str.length;i>0;i--){
var newstr = str.substring(0,i)
reverse += newstr.substr(-1,1)
}
return reverse;
}

- 762
- 11
- 12
OK, pretty simple, you can create a function with a simple loop to do the string reverse for you without using reverse()
, charAt()
etc like this:
For example you have this string:
var name = "StackOverflow";
Create a function like this, I call it reverseString
...
function reverseString(str) {
if(!str.trim() || 'string' !== typeof str) {
return;
}
let l=str.length, s='';
while(l > 0) {
l--;
s+= str[l];
}
return s;
}
And you can call it like:
reverseString(name);
And the result will be:
"wolfrevOkcatS"

- 100,211
- 27
- 269
- 172
Here are the four most common methods you can use to achieve a string reversal
Given a string, return a new string with the reversed order of characters
Multiple Solutions to the problem
//reverse('apple') === 'leppa'
//reverse('hello') === 'olleh'
//reverse('Greetings!') === '!sgniteerG'
// 1. First method without using reverse function and negative for loop
function reverseFirst(str) {
if(str !== '' || str !==undefined || str !== null) {
const reversedStr = [];
for(var i=str.length; i>-1; i--) {
reversedStr.push(str[i]);
}
return reversedStr.join("").toString();
}
}
// 2. Second method using the reverse function
function reverseSecond(str) {
return str.split('').reverse().join('');
}
// 3. Third method using the positive for loop
function reverseThird(str){
const reversedStr = [];
for(i=0; i<str.length;i++) {
reversedStr.push(str[str.length-1-i])
}
return reversedStr.join('').toString();
}
// 4. using the modified for loop ES6
function reverseForth(str) {
const reversedStr = [];
for(let character of str) {
reversedStr = character + reversedStr;
}
return reversedStr;
}
// 5. Using Reduce function
function reverse(str) {
return str.split('').reduce((reversed, character) => {
return character + reversed;
}, '');
}

- 1,032
- 11
- 14
use this method if you are more curious about performance and time complexity. in this method i have divided string in two part and sort it in length/2 times loop iteration.
let str = "abcdefghijklmnopqrstuvwxyz"
function reverse(str){
let store = ""
let store2 = ""
for(let i=str.length/2;i>=0;i--){
if(str.length%2!==0){
store += str.charAt(i)
store2 += str.slice((str.length/2)+1, str.length).charAt(i)
}else{
store += str.charAt(i-1)
store2 += str.slice((str.length/2), str.length).charAt(i)
}
}
return store2+store
}
console.log(reverse(str))
it is not optimal but we can think like this.

- 898
- 9
- 24
-
1it is bit complected, but it is something new. we can think like this. – code7004 Jun 13 '20 at 14:32
ES6
function reverseString(str) {
return [...str].reverse().join("");
}
console.log(reverseString("Hello")); // olleH

- 109
- 1
- 4
-
-
1If I have to interpret, he created a function that passes in `str` a string. This function puts the string inside an array `[...str]`. If you pass in the string "hello" for example, it would translate to this `["h", "e", "l", "l", "o"]` Then all array methods can be applied. He reversed the elements of the array, then he joined it with `("")` which means no white space in between chars. – Gel Nov 09 '21 at 13:28
-
1Please check other answers before posting to ensure you're not reposting answers that have already been given (eg: these posted one 1 year prior to yours: see [here](https://stackoverflow.com/a/64147373/5648954) and [here](https://stackoverflow.com/a/959004/5648954)) – Nick Parsons Mar 22 '22 at 11:55
function reverse_string(string)
{
var string;
var len = string.length;
var stringExp = string.split('');
var i;
for (i = len-1; i >=0;i--)
{
var result = document.write(stringExp[i]);
}
return result;
}
reverse_string("This is a reversed string");
//outputs: gnirts desrever a si sihT

- 81
- 1
- 1
- 7
without converting string to array;
String.prototype.reverse = function() {
var ret = "";
var size = 0;
for (var i = this.length - 1; -1 < i; i -= size) {
if (
'\uD800' <= this[i - 1] && this[i - 1] <= '\uDBFF' &&
'\uDC00' <= this[i] && this[i] <= '\uDFFF'
) {
size = 2;
ret += this[i - 1] + this[i];
} else {
size = 1;
ret += this[i];
}
}
return ret;
}
console.log('anãnam anañam' === 'mañana mañana'.reverse());
using Array.reverse without converting characters to code points;
String.prototype.reverse = function() {
var array = this.split("").reverse();
for (var i = 0; i < this.length; ++i) {
if (
'\uD800' <= this[i - 1] && this[i - 1] <= '\uDBFF' &&
'\uDC00' <= this[i] && this[i] <= '\uDFFF'
) {
array[i - 1] = array[i - 1] + array[i];
array[i] = array[i - 1].substr(0, 1);
array[i - 1] = array[i - 1].substr(1, 1);
}
}
return array.join("");
}
console.log('anãnam anañam' === 'mañana mañana'.reverse());

- 4,540
- 1
- 39
- 42
-
For the second version: `var c = array[i-1]; array[i-1] = array[i]; array[i] = c;` does not require concatenating the code pair. Also, the for-loop should start at 1. – MT0 Jan 09 '17 at 13:11
-
The second version does not work with `'\ud83c\ud83c\udfa5'.reverse()` - it will output the same as the input. Adding `++i;` within the `if` statement should fix this. – MT0 Jan 09 '17 at 13:22
-
On second thoughts - this does not handle combining diacritics: `'a\u0303bc'.reverse() === 'cba\u0303'` should return true. – MT0 Jan 09 '17 at 14:33
function reverse(str){
var s = "";
for (var i = str.length - 1; i >= 0; i--){
s += str[i];
}
return s;
};
reverse("your string comes here")

- 1,099
- 1
- 19
- 41
The below might help anyone that is looking to reverse a string recursively. Was asked to do this in a recent job interview using functional programming style:
var reverseStr = function(str) {
return (str.length > 0) ? str[str.length - 1] + reverseStr(str.substr(0, str.length - 1)) : '';
};
//tests
console.log(reverseStr('setab retsam')); //master bates

- 616
- 7
- 10
Adding to the String prototype is ideal (just in case it gets added into the core JS language), but you first need to check if it exists, and add it if it doesn't exist, like so:
String.prototype.reverse = String.prototype.reverse || function () {
return this.split('').reverse().join('');
};
Something like this should be done following the best practices:
(function(){
'use strict';
var str = "testing";
//using array methods
var arr = new Array();
arr = str.split("");
arr.reverse();
console.log(arr);
//using custom methods
var reverseString = function(str){
if(str == null || str == undefined || str.length == 0 ){
return "";
}
if(str.length == 1){
return str;
}
var rev = [];
for(var i = 0; i < str.length; i++){
rev[i] = str[str.length - 1 - i];
}
return rev;
}
console.log(reverseString(str));
})();

- 17,953
- 10
- 93
- 108
var reverseString = function(str){
let length = str.length - 1;
str = str.split('');
for(let i=0;i<= length;i++){
str[length + i + 1] = str[length - i];
}
return str.splice(length + 1).join('');
}

- 1,017
- 2
- 16
- 26
No built-in methods? Given that strings in Javascript are immutable, you probably want to use the in-built methods like split, join, and so on. But here are two ways to go without those methods:
function ReverseString(str) {
var len = str.length;
var newString = [];
while (len--) {
newString.push(str[len]);
}
return newString.join('');
}
console.log(ReverseString('amgod')) //dogma
function RecursiveStringReverse(str, len) {
if (len === undefined)
len = str.length - 1;
if (len > 0)
return str[len] + RecursiveReverse(str, --len);
return str[len];
}
console.log(RecursiveStringReverse('Hello, world!'))// !dlrow ,olleH

- 523
- 6
- 11
Added for reverse of string without loop, it's working through recursion.
function reverse(y){
if(y.length==1 || y.length == 0 ){
return y;
}
return y.split('')[y.length - 1]+ reverse(y.slice(0, y.length-1));
}
console.log(reverse("Hello"));

- 186
- 1
- 5
- 17

- 23
- 5
-
2It will be good if you could edit your post and post your code as text rather then image. - [from review](https://stackoverflow.com/review/late-answers/25248608) – Vivek Mehta Feb 02 '20 at 13:21
function reverse(string)
{
let arr = [];
for(let char of string) {
arr.unshift(char);
}
let rev = arr.join('')
return rev
}
let result = reverse("hello")
console.log(result)

- 19
- 3
var str = "IAMA JavaScript Developer";
var a=str.split(''), b = a.length;
for (var i=0; i<b; i++) {
a.unshift(a.splice(1+i,1).shift())
}
a.shift();
alert(a.join(''));

- 7,016
- 3
- 19
- 18
We can iterate the string array from both the ends: start and end, and swap at each iteration.
function reverse(str) {
let strArray = str.split("");
let start = 0;
let end = strArray.length - 1;
while(start <= end) {
let temp = strArray[start];
strArray[start] = strArray[end];
strArray[end] = temp;
start++;
end--;
}
return strArray.join("");
}
Although the number of operations have reduced, its time complexity is still O(n) as the number of operations still scale linearly with the size of input.
Ref: AlgoDaily

- 2,694
- 1
- 29
- 22
One of the way could also be using reduce method to reverse after using split method.
function reverse(str) {
return str.split('').reduce((rev, currentChar) => currentChar + rev, '');
}
console.log(reverse('apple'));
console.log(reverse('hello'));
console.log(reverse('Greetings!'));

- 1,183
- 1
- 10
- 25
function reverseWords(str) {
// Go for it
const invertirPalabra = palabra => palabra.split('').reverse().join('')
return str.split(' ').map(invertirPalabra).join(' ')
// con split convierto string en array de palabras, le paso ' '
// que es que me lo separe por espacios
// luego invierto cada palabra...
// y luego con join las uno separando por espacios
}

- 51
- 2
You could try something like this. I'm sure there's some room for refactoring. I couldn't get around using the split function. Maybe someone knows of a way to do it without split.
Code to set up, can put this in your .js library
Code to use it (has client side code, only because it was tested in a browser):
var sentence = "My Stack is Overflowing."
document.write(sentence.reverseLetters() + '<br />');
document.write(sentence.reverseWords() + '<br />');
Snippet:
String.prototype.aggregate = function(vals, aggregateFunction) {
var temp = '';
for (var i = vals.length - 1; i >= 0; i--) {
temp = aggregateFunction(vals[i], temp);
}
return temp;
}
String.prototype.reverseLetters = function() {
return this.aggregate(this.split(''),
function(current, word) {
return word + current;
})
}
String.prototype.reverseWords = function() {
return this.aggregate(this.split(' '),
function(current, word) {
return word + ' ' + current;
})
}
var sentence = "My Stack is Overflowing."
document.write(sentence.reverseLetters() + '<br />');
document.write(sentence.reverseWords() + '<br />');

- 11,803
- 11
- 66
- 93

- 1,934
- 1
- 16
- 21
Another variation (does it work with IE?):
String.prototype.reverse = function() {
for (i=1,s=""; i<=this.length; s+=this.substr(-i++,1)) {}
return s;
}
EDIT:
This is without the use of built-in functions:
String.prototype.reverse = function() {
for (i=this[-1],s=""; i>=0; s+=this[i--]) {}
return s;
}
Note: this[-1] holds a length of the string.
However it's not possible to reverse the string in place, since the assignment to individual array elements doesn't work with String object (protected?). I.e. you can do assigns, but the resulting string doesn't change.

- 3,189
- 2
- 20
- 32
// try this simple way
const reverseStr = (str) => {
let newStr = "";
for (let i = str.length - 1; i >= 0; i--) {
newStr += str[i];
}
return newStr;
}
console.log(reverseStr("ABCDEFGH")); //HGFEDCBA

- 1,117
- 9
- 9
I guess, this will work for you
function reverse(str){
str = str.split("").reverse().join("").split(" ").reverse().join(" ");
console.log(str)
}

- 2,074
- 1
- 18
- 23

- 128
- 2
- 10
It is not possible to reverse a string in place, but it is possible to do it not in place.

- 423
- 4
- 14