The Gotcha

The sort() method for Javascript arrays does not sort numbers in numerical order:

myArray = [40, 200, 500, 3, 8, 10];
myArray.sort();
// Result: Array(6) [ 10, 200, 3, 40, 500, 8 ]

Why it Happens

The default sort() method coerces each array element to a string before the elements are sorted. When strings are sorted, they are sorted in lexicographical (alphabetical) order and not numerical order.

Similarly strange results will occur when a null or undefined element is coerced to "null" or "undefined".

The Fix

Minor warning: neither of the below solutions work in Internet Explorer. Sigh.

Solution 1: Write a custom comparator

The sort() method accepts a comparator function as an argument. Comparators should take in two arguments (a and b) and return these outputs:

  • if a < b, return a negative number
  • if a == b, return 0
  • if a > b, return a positive number

Using a comparator will override the default lexographical sort, enabling a proper numerical sort:

myArray.sort(function(a, b) {
  return a - b;
});

Or the ES6 version with arrow functions:

myArray.sort((a, b) => a - b);

This solution is simple and generally accepted as the right way to solve this gotcha within the Javascript community.

Solution 2: Use a TypedArray

The ES6 TypedArray is an array-like API for binary data. When it comes to sorting, the TypedArray implements a numerical sort by default:

new Int16Array(myArray).sort()
// Outputs: Int16Array(6) [ 3, 8, 10, 40, 200, 500 ]

Though less commonly used compared to the first solution, it's more performant.

Conclusion

Even though I understand technically why this gotcha happens, I still don't understand the reasoning behind why Javascript was implemented this way. Is there some use case I'm not thinking of for sorting numbers in lexicographical order? Was it just simpler to only implement a lexicographical sort? I don't know, and I couldn't seem to find satisfactory answers online.

Maybe it's just me, but sorting numbers numerically seems like basic functionality that every language should have. Javascript, why don't you have this?