The sort method behaves different on different browsers

Tell us what’s happening:
The example function reverseAlpha function doesn’t work on Chrome (works on FireFox).

function reverseAlpha(arr) {
  return arr.sort(function(a, b) {
    return a < b;
  });
}

The slightly modified version works on both Chrome and Firefox:

function reverseAlpha(arr) {
  return arr.sort(function(a, b) {
    return a < b ? 1 : -1;
  });
}

Is this a JavaScript version issue?

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/functional-programming/sort-an-array-alphabetically-using-the-sort-method/

Which dataset are you working on? numbers or letters?

Letters, e.g. [“a”, “d”, “c”, “a”, “z”, “g”]. The example code produces [“a”, “d”, “c”, “a”, “z”, “g”] as the sorted result on Chrome.

The callback for sort should return 1, 0 or -1, and the first function does not do that, so strictly speaking Chrome is correct.

But browser engines can implement JS however they fancy, so, yes, you’ll sometimes get different results for things like sort. The spec says nothing about how the underlying engine should be implemented: sort will be implemented however the vendor has decided is the most efficient way that works with their code; in this case FF could be coercing the boolean to 0 or 1 possibly?

You are right. Here is some code that better defines the problem:
Chrome console:

   ["a", "b", "c", "b", "a"].sort()
=> ["a", "a", "b", "b", "c"]

   ["a", "b", "c", "b", "a"].sort((x,y)=>x>y)
=> ["a", "b", "c", "b", "a"]

   ["a", "b", "c", "b", "a"].sort((x,y)=>x<y)
=> ["a", "b", "c", "b", "a"]

   ["a", "b", "c", "b", "a"].sort((x,y)=>x>y?1:-1)
=> ["a", "a", "b", "b", "c"]

Firefox console:

   ["a", "b", "c", "b", "a"].sort()
=> ["a", "a", "b", "b", "c"]

   ["a", "b", "c", "b", "a"].sort((x,y)=>x>y)
=> ["a", "a", "b", "b", "c"]

   ["a", "b", "c", "b", "a"].sort((x,y)=>x<y)
=> ["c", "b", "b", "a", "a"]

When we compare a and b, there are three possible outcomes: a>b, a==b, or a<b. If a>b is false it implies that a<=b. So a yes or no answer to a>b? is all we need to sort an array. To prove this, I implemented the bubble sort algorithm (in the following jsbin), which is insensitive to what the callback returns {0,1} or {-1,1}:

If you try the jsbin on Chrome, one of the test will fail. I still don’t understand why Chrome’s implementation of sort() is sensitive.

It isn’t really being sensitive, your code is technically wrong for both callbacks. AFAIK, for a stable sort in Chrome, the callback has to return -1, 0 or 1 (or -n, ±0, +n which would be normalised to -1, 0 and 1 anyway). The fact it happens to work in FF is just a thing at this current point in time; it could change tomorrow. Chrome had an open issue for ages to fix sort so that is was stable, so they did fairly recently (I think September? They’re using Timsort anyway if you’re super interested in sorting algorithms or whatever)

I’d advise just returning the correct thing from the sort function though: it’s not supposed to be a boolean and trying to rely on browsers working strangely isn’t a good idea

Thanks. You are right. (x,y)=>x>y is technically wrong because it returns true->1 if a>b and otherwise false->0, which is interpreted by sort() as a==b. We should not rely on the quirky behavior of FF. Maybe freecodecamp should update their starter code so that it is correct and works on all browsers.

1 Like