21

Consider the following code (React JS code):

  poll() {
    var self   = this;
    var url    = "//" + location.hostname + "/api/v1/eve/history/historical-data/" + this.state.itemId + '/' + this.state.regionId + '/40';

    $.get(url, function(result) {
      console.log(result.data, result.data.reverse());
      self.setState({
        error:          null,
        historicalData: result.data.reverse(),
        isLoading: false
      });
    }).fail(function(response) {
      self.setState({
        error: 'Could not fetch average price data. Looks like something went wrong.',
      });
    });
  }

Notice the console.log. Lets see an image:

enter image description here

Last I checked, reverse should have reversed the order of the array. Yet it doesn't.

Am I Using this wrong (official MDN Docs)? Why isn't reverse working?

TheWebs
  • 12,470
  • 30
  • 107
  • 211
  • 3
    From the MDN docs: "The `reverse()` method reverses an array _in place_." (emphasis not mine) – JLRishe Mar 03 '16 at 19:00
  • I tried this thinking I could do: `result.data.reverse()` then just `console.log()` `result.data`. Alas it is not reversed – TheWebs Mar 03 '16 at 19:17
  • No, it _is_ reversed. The console in whatever browser you're using shows objects in their current state, so `result.data.reverse(); console.log(result.data);` will give you exactly the same output as `console.log(result.data); result.data.reverse();` – JLRishe Mar 03 '16 at 19:47
  • 1
    But this doesn't help me at all because when the data is placed into charts the labels read from today to yesterday when if it was reversed they would read yesterday to today – TheWebs Mar 03 '16 at 19:49
  • Your code above calls `result.data.reverse()` twice. This means that when your array is shown, it will be in its original order. Have you _tried_ using code that only calls `result.data.reverse()` once? – JLRishe Mar 03 '16 at 20:05
  • It's not reversed even if I remove the console log – TheWebs Mar 03 '16 at 20:06

6 Answers6

19

It has reversed it, the reverse() is executed before the console.log(). It mutates the actual array first in place returning a reference so then when it is logged, a is also reversed.

var a = [1,2,3,4];
console.log(a, a.reverse());
// [4, 3, 2, 1] [4, 3, 2, 1]

Everything inside the console.log parens is evaluated first. Try 2 reverses, can you guess what happens, it goes back to original order, like in your example.

var a = [1,2,3,4]
console.log(a, a.reverse());
// [4, 3, 2, 1] 
Matt Harrison
  • 13,381
  • 6
  • 48
  • 66
  • 3
    So I did: `var reversedData = result.data.reverse(); console.log(reversedData);` Still the array is not reversed. it shows the exact same as before. Some one suggested its because i call reverse else where, but never the less this piece of code does not reverse the array. I am unsure why. – TheWebs Mar 03 '16 at 19:13
  • In your example you call `result.data.reverse()` twice. So it's going back to original order. – Matt Harrison Mar 03 '16 at 19:16
  • @KyleAdams Your screenshot is `already` showing the array in reversed order. Remove all calls to `result.data.reverse()` and log `result.data` to the console, and I think you will see it in its original order. – JLRishe Mar 03 '16 at 19:46
10

reverse is destructive -- it changes the original array.

MDN Docs Array Reverse

example -

let a = [1,2,3,4]
console.log(a, a.reverse()) // [4,3,2,1],[4,3,2,1] 

It mutates the actual array first in place returning a reference

Solution

let a = [1,2,3,4]
let reverseArray = [...a].reverse()
console.log(a, reverseArray) // [1,2,3,4], [4,3,2,1]
Junip Dewan
  • 759
  • 8
  • 8
  • If I'm not mistaken, you need to call reverse on the second line of your solution. `let reverseArray = [...a].reverse();` Otherwise you get two identical copies of the original array `[1,2,3,4]`. – Eduardo06sp Apr 18 '21 at 18:21
  • Thanks, @Eduardo06sp for the corrections – Junip Dewan Sep 30 '21 at 04:33
  • In React, my state getter is an array so `[...arrayValue]` to remove the reference worked – Zac Oct 01 '22 at 18:49
6

As described at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse, reverse() reverses the order of an array in place, so the array is reversed after it's been called. You're calling it twice, resulting in the array being restored to its original order. Try this:

poll() {
    var self   = this;
    var url    = "//" + location.hostname + "/api/v1/eve/history/historical-data/" + this.state.itemId + '/' + this.state.regionId + '/40';

    $.get(url, function(result) {
        result.data.reverse();
        console.log(result.data, result);
        self.setState({
            error:          null,
            historicalData: result,
            isLoading: false
        });
    }).fail(function(response) {
        self.setState({
            error: 'Could not fetch average price data. Looks like something went wrong.',
    });
}
AmericanUmlaut
  • 2,817
  • 2
  • 17
  • 27
  • No you do not understand. I am calling it once. Yes twice. But look at the console log. The console log is the first time. even if i remove the console.log, the array is NOT reversed. – TheWebs Mar 03 '16 at 19:10
  • Have you understood Matt Harrison's answer? The console is logging the array in reverse order twice, because it's evaluating the reverse() call before logging. – AmericanUmlaut Mar 03 '16 at 19:46
6

The source of your problem is that you don't understand how your browser's console works.

Many browsers have consoles that display objects in the state they are in when you expand them in the console or when you open the console, even if they change after console.log() is called. So if you do:

console.log(result.data);
result.data.reverse();
console.log(result.data);

you will see the same output twice. The second line reverses the array in place, so both log outputs are showing the same array, in its present state.

To demonstrate this console behavior, you can do the following:

var b = { a: [1, 2, 3] };
console.log(b);
b.a[1] = 9;
console.log(b);

what you will see is that b.a is [1, 9, 3] in both console outputs.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
3

Initially your array was mutated thus causing it to appear normally. With below solution it mutates the array twice thus reverses the actual array to get the expected result.

Solution: [...result.data].reverse()

Nil_Syami
  • 31
  • 2
0

if you have a sortable property within your array of objects, 'sort' will do the rearranging after pushing an item in items

say,

let items = [{id: 1, color: 'blue'}, {id: 2, color: 'red'}];
let item = {id: 10, color: 'green'};
items.push(item);

items.sort((a, b)=>{
    return b.id - a.id  //this will sort according to .id descending
});