Array.prototype.reverse()
reverse() Syntax
reverse()
Array.prototype.reverse() takes no parameters. Any arguments you pass are silently ignored. It returns the same array reference, with the elements reordered in place.
Description
reverse() mutates the array it is called on and returns that same array (not a copy). The element that was at index i ends up at index n - 1 - i, where n is the array’s length. The length itself is preserved.
The method is generic. If you call it on an array-like object (one with a length property and integer-keyed properties), it operates on that object instead. The method is not usable on strings directly, since strings are immutable; calling Array.prototype.reverse.call("abc") throws a TypeError.
reverse() has been in JavaScript since ECMAScript 1 (1997). It works in every browser and every Node.js release without a polyfill.
Examples
Basic reversal
const items = [1, 2, 3];
items.reverse();
console.log(items); // [3, 2, 1]
The return value is the same reference
reverse() does not produce a new array. The variable on the right side of the assignment is the same object you started with, just with its elements in the opposite order. The strict equality check in the snippet below makes that explicit by comparing the returned value to the original with ===:
const numbers = [3, 2, 4, 1, 5];
const reversed = numbers.reverse();
console.log(reversed === numbers); // true
console.log(numbers); // [5, 1, 4, 2, 3]
Because the return is the same array, anything that mutates the returned value also mutates the original. There is no hidden copy sitting behind the returned reference, so writing to an index through the returned variable changes the array you started with. That property is what makes reverse dangerous inside React state updates, reducers, and any other code that assumes inputs stay intact. The next snippet demonstrates it by assigning to the first index of the result and then logging the original:
const a = [1, 2, 3];
const r = a.reverse();
r[0] = 99;
console.log(a); // [99, 2, 1]
This is the most common surprise with reverse. Methods like map, filter, and slice return new arrays, so it’s tempting to assume reverse does too. It does not.
Empty and single-element arrays are no-ops
console.log([].reverse()); // []
console.log([42].reverse()); // [42]
Sparse arrays stay sparse
Empty slots are moved along with the data; they are not filled in with undefined. The result is a sparse array of the same shape, with the holes simply shifted to their new positions. Code that distinguishes holes from explicit undefined (for example, a check with Object.hasOwn(arr, i) or the in operator) keeps working after the reversal, because the algorithm preserves the hole-vs-defined distinction at every index. The snippet below shows this for two different starting shapes:
console.log([1, , 3].reverse()); // [3, <empty>, 1]
console.log([1, , 3, 4].reverse()); // [4, 3, <empty>, 1]
If your code distinguishes holes from explicit undefined values (for example with Object.hasOwn(arr, i) or i in arr), that distinction survives the reversal.
Array-like objects
reverse does not require the receiver to be a real Array. Any object with a length and integer-indexed properties works:
const arrayLike = { length: 3, 2: "c" };
const result = Array.prototype.reverse.call(arrayLike);
console.log(result); // { 0: 'c', length: 3 }
The swap moves the "c" from index 2 to index 0, and the algorithm deletes the source index after reading it, so index 2 ends up gone (a missing property, not undefined).
Reversing a string
Strings are immutable, so Array.prototype.reverse.call("abc") throws. Spread the string into a real array first, reverse, then join back:
const str = "hello";
const reversed = [...str].reverse().join("");
console.log(reversed); // "olleh"
Array.from(str).reverse().join("") works the same way. Both approaches allocate a fresh array, run reverse() on that throwaway, and stitch the characters back together with join(""). The intermediate reverse() call still mutates the temporary array, but the source string and any other variable in scope are never touched. Strings themselves are immutable, so the trick is really about reaching a method that works on strings via an array detour.
Reverse without mutating
There are plenty of situations where you want a reversed view of an array but you cannot afford to mutate the original. A reducer, a React state update, and a function that returns a derived list are all common examples, and in each of them touching the input would either break a memo check or surprise a caller. The standard fix is to copy the array first, then reverse the copy, leaving the source untouched. The snippet below copies with the spread syntax, which is the shortest way to get a shallow clone in modern JavaScript:
const original = [3, 1, 2];
const reversed = [...original].reverse();
console.log(original); // [3, 1, 2]
console.log(reversed); // [2, 1, 3]
The spread-then-reverse pattern works everywhere, including engines that predate ES2023. The same effect has been baked into the language directly: Array.prototype.toReversed() (ES2023) returns a fresh array with the elements in reverse order and leaves the receiver alone, which is the version you would reach for on a modern runtime. Both snippets below produce the same output, but only the second one goes through a temporary intermediate array:
const original = [3, 1, 2];
const reversed = original.toReversed();
console.log(original); // [3, 1, 2]
console.log(reversed); // [2, 1, 3]
toReversed requires Chrome 110+, Edge 110+, Firefox 115+, Safari 16+, or Node.js 20+. On older engines, the spread-then-reverse pattern is the safer choice.
Common Mistakes
Chaining mutates the same array twice. arr.reverse().sort() reverses and then sorts the same reference. If you wanted a sorted copy of a reversed view, copy first:
const a = [3, 1, 2];
const sortedCopy = [...a].reverse().sort();
console.log(a); // [3, 1, 2]
console.log(sortedCopy); // [1, 2, 3]
Treating the return as a new array. Code that does const b = a.reverse(); and then assumes a is unchanged is a frequent source of bugs in React state updates, reducers, and other functional flows. Either copy first or reach for toReversed.
Passing arguments. reverse ignores any arguments. [1, 2, 3].reverse(true) still returns [3, 2, 1]. There is no comparator-style callback like the one sort accepts.
Assuming a reversed copy sorts as a side effect. sort is also in-place, so [...a].reverse().sort() is fine, but a.reverse().sort() mutates a twice. Watch which reference you’re sorting.
Browser Support
Array.prototype.reverse is in ECMAScript 1 and ships in every JavaScript engine. No polyfill is needed, and there are no spec-compatibility caveats. The only modern counterpart worth knowing is toReversed (ES2023), which provides a non-mutating version for environments that support it.