admin管理员组

文章数量:1127049

Array.prototype.reverse reverses the contents of an array in place (with mutation)...

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation)?

Array.prototype.reverse reverses the contents of an array in place (with mutation)...

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation)?

Share Improve this question edited Aug 22, 2023 at 6:58 Peter Mortensen 31.6k22 gold badges109 silver badges133 bronze badges asked Jun 3, 2015 at 3:49 sfletchesfletche 49.6k31 gold badges108 silver badges120 bronze badges 2
  • 1 possible duplicate of Making an independent copy of a reversed array in JavaScript – Bergi Commented Jun 3, 2015 at 3:59
  • Here's a benchmark comparing the different options: jsben.ch/HZ7Zp – Solomon Ucko Commented Jun 13, 2019 at 18:55
Add a comment  | 

17 Answers 17

Reset to default 713

You can use slice() to make a copy then reverse() it

var newarray = array.slice().reverse();

var array = ['a', 'b', 'c', 'd', 'e'];
var newarray = array.slice().reverse();

console.log('a', array);
console.log('na', newarray);

2023

const newArray = array.toReversed()

Array.prototype.toReversed()

In ES6:

const newArray = [...array].reverse()

const originalArray = ['a', 'b', 'c', 'd', 'e', 'f'];

const newArray = Array.from(originalArray).reverse();

console.log(newArray);

ES2023 Array Method toReversed()

From the linked documentation:

The toReversed() method transposes the elements of the calling array object in reverse order and returns a new array.

const items = [1, 2, 3];
console.log(items); // [1, 2, 3]

const reversedItems = items.toReversed();
console.log(reversedItems); // [3, 2, 1]
console.log(items); // [1, 2, 3]

Browser compatibility

Another ES6 variant:

We can also use .reduceRight() to create a reversed array without actually reversing it.

let A = ['a', 'b', 'c', 'd', 'e', 'f'];

let B = A.reduceRight((a, c) => (a.push(c), a), []);

console.log(B);

Useful Resources:

  • Array.prototype.reduceRight()
  • Arrow Functions
  • Comma Operator

There are multiple ways of reversing an array without modifying. Two of them are

var array = [1,2,3,4,5,6,7,8,9,10];

// Using slice
var reverseArray1 = array.slice().reverse(); // Fastest

// Using spread operator
var reverseArray2 = [...array].reverse();

// Using for loop 
var reverseArray3 = []; 
for(var i = array.length-1; i>=0; i--) {
  reverseArray.push(array[i]);
}

Performance test http://jsben.ch/guftu

Try this recursive solution:

const reverse = ([head, ...tail]) => 
    tail.length === 0
        ? [head]                       // Base case -- cannot reverse a single element.
        : [...reverse(tail), head]     // Recursive case

reverse([1]);               // [1]
reverse([1,2,3]);           // [3,2,1]
reverse('hello').join('');  // 'olleh' -- Strings too!                              

An ES6 alternative using .reduce() and spreading.

const foo = [1, 2, 3, 4];
const bar = foo.reduce((acc, b) => ([b, ...acc]), []);

Basically what it does is create a new array with the next element in foo, and spreading the accumulated array for each iteration after b.

[]
[1] => [1]
[2, ...[1]] => [2, 1]
[3, ...[2, 1]] => [3, 2, 1]
[4, ...[3, 2, 1]] => [4, 3, 2, 1]

Alternatively .reduceRight() as mentioned above here, but without the .push() mutation.

const baz = foo.reduceRight((acc, b) => ([...acc, b]), []);

There's a new tc39 proposal, which adds a toReversed method to Array that returns a copy of the array and doesn't modify the original.

Example from the proposal:

const sequence = [1, 2, 3];
sequence.toReversed(); // => [3, 2, 1]
sequence; // => [1, 2, 3]

As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.

const arrayCopy = Object.assign([], array).reverse()

This solution:

-Successfully copies the array

-Doesn't mutate the original array

-Looks like it's doing what it is doing

Update 2023:

Array.prototype.toReversed() is the new ES2023 method for returning a reversed array, without modifying the original one.

const items = [1, 2, 3];
console.log(items); // [1, 2, 3]
    
const reversedItems = items.toReversed();
console.log('reversedItems', reversedItems); // [3, 2, 1]
console.log('items', items); // [1, 2, 3]

It's also possible to use it on sparse arrays: console.log([1, , 3].toReversed()); // [3, undefined, 1] and on non-array objects

Reversing in place with variable swap just for demonstrative purposes (but you need a copy if you don't want to mutate)

const myArr = ["a", "b", "c", "d"];
const copy = [...myArr];
for (let i = 0; i < (copy.length - 1) / 2; i++) {  
    const lastIndex = copy.length - 1 - i; 
    [copy[i], copy[lastIndex]] = [copy[lastIndex], copy[i]] 
}

Jumping into 2022, and here's the most efficient solution today (highest-performing, and no extra memory usage).


For any ArrayLike type, the fastest way to reverse is logically, by wrapping it into a reversed iterable:

function reverse<T>(input: ArrayLike<T>): Iterable<T> {
    return {
        [Symbol.iterator](): Iterator<T> {
            let i = input.length;
            return {
                next(): IteratorResult<T> {
                    return i
                        ? {value: input[--i], done: false}
                        : {value: undefined, done: true};
                },
            };
        },
    };
}

This way you can reverse-iterate through any Array, string or Buffer, without any extra copy or processing for the reversed data:

for(const a of reverse([1, 2, 3])) {
    console.log(a); //=> 3 2 1
}

It is the fastest approach, because you do not copy the data, and do no processing at all, you just reverse it logically.

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation) ?

Yes, there is a way to achieve this by using to[Operation] that return a new collection with the operation applied (This is currently at stage 3, will be available soon).

Implementation will be like :

const arr = [5, 4, 3, 2, 1];

const reversedArr = arr.toReverse();

console.log(arr); // [5, 4, 3, 2, 1]

console.log(reversedArr); // [1, 2, 3, 4, 5]

Not the best solution but it works

Array.prototype.myNonMutableReverse = function () {
  const reversedArr = [];
  for (let i = this.length - 1; i >= 0; i--) reversedArr.push(this[i]);
  return reversedArr;
};

const a = [1, 2, 3, 4, 5, 6, 7, 8];
const b = a.myNonMutableReverse();
console.log("a",a);
console.log("////////")
console.log("b",b);

If you're using an older version of Node (<20), where .reverse() and .toReversed() are not available, here's the shortest one-liner alternative I could come up with:

console.log([1,2,3].map((_, i, a) => a[a.length - 1 - i])); // [3,2,1]

/** Reverses an array without mutating the original. */
export function revArr<T>(arr: T[]): T[] {
  return arr.map((_, i, a) => a[a.length - 1 - i]);
}

es6:

const reverseArr = [1,2,3,4].sort(()=>1)

本文标签: Reverse an array in JavaScript without mutating the original arrayStack Overflow