Skip to Content
Index

Sorting out JavaScript

Dealing with a major, unintuitive feature.

JavaScript, with its dynamic typing, cannot presume a consistent input for any function. This is pretty much the biggest hold-up with anything to do with this language.

Sorting a list in JavaScript is a common pitfall for beginners, especially for impatient folks ready to skip the docs (including me). Or perhaps “impatient” is unfair to everyone who misunderstood this in-built function, as it is an easy thing to overlook.

Array.prototype.sort(), by default, can be used for an array of multiple kinds of element. So for an array with numbers and strings we can’t assume a numeric comparison. In such a case, it kind of makes sense to compare all elements by the lexicographic order instead.

const mixed = ['zero', 45, 555, 3, 444, 36, 'ajit'];

console.log(mixed.sort());
// -> [3, 36, 444, 45, 555, "ajit", "zero"]

See what happened there?

But now if you were quick to assume this behaviour occurs just because we included strings into the mix, then you would be wrong.

const mixed = [45, 555, 3, 444, 36];

console.log(mixed.sort());
// -> [3, 36, 444, 45, 555]

By default, comparisons occur by coercing the type of the element to string.

So, if you want a numeric comparison (for obvious reasons), we can pass a comparator function like so:

const mixed = [45, 555, 3, 444, 36];
const comparatorFn = (previousValue, currentValue) => {
	// hacky magic, expects negative/positive stuff, idk/idc
	return previousValue - currentValue;
};

console.log(mixed.sort(comparatorFn));
// -> [3, 36, 45, 444, 555]

Another catch: Your list of numbers shouldn’t contain Infinity or NaN with this particular comparator. That should be an entirely different article, but in short, previousValue - currentValue for anything involving these values will always result in the same value.

This is just me writing notes for myself at this point. Hope this helps someone.


Filed on under #javascript