Sorting Objects in JavaScript

Abstract image used to represent Sorting Objects in JavaScript
Image by Tim Gouw.

When working with arrays of objects in JavaScript, the Array.prototype.sort() method requires a bit more finesse simply because you are dealing with properties of objects rather than individual values.


Understanding Comparator Functions for Objects

A comparator function for sorting an array of objects must be provided to the sort() method in order to define the specific property or properties that you want the object sorted by.

This function should take two parameters (conventionally, these are named a and b), which represent the objects being compared.


The Comparator's Return Values

The comparator function must return a value that tells the sort() method how to order the two elements a and b:

  • If it returns a negative number, sort() will place a before b.
  • If it returns zero, it will leave a and b unchanged with respect to each other, but sorted with respect to all different elements.
  • If it returns a positive number, sort() will place b before a.

Sorting Objects by a Numeric Property

The most common use case I come across is numeric sorting: products by price, electric vehicles by battery range, or flights by the number of layovers. For the kinds of projects behind those examples, see my work with John Lewis, Selfridges, Polestar and Virgin Atlantic.

So, suppose we have an array of objects where each object has a price property and we want to sort the array in ascending order of prices:

const products = [
  {
    name: 'iPhone 13 mini',
    price: 699,
  },
  {
    name: 'iPhone SE (3rd generation)',
    price: 429 },
  {
    name: 'iPhone 13 Pro',
    price: 999,
  },
  {
    name: 'iPhone 13 Pro Max',
    price: 1099,
  },
  {
    name: 'iPhone 13',
    price: 799,
  },
];

products.sort((a, b) => a.price - b.price);

Here, the comparator function (a, b) => a.price - b.price calculates the difference between the price of each product. If a is less expensive than b, then it returns a negative value, placing a before b.


Sorting Objects by a String Property

If you want to sort by a string property, such as the name of a product, you'll need a different approach since you cannot subtract strings.

I also need to use a different example here because sorting by different iPhone models when they all start with the word 'iPhone' isn't terribly illustrative! So, here goes:

const products = [
  { name: 'Notebook', price: 9.99 },
  { name: 'Pencil', price: 1.7 },
  { name: 'Backpack', price: 19.99 },
];

products.sort((a, b) => {
  if (a.name < b.name) {
    return -1;
  }
  if (a.name > b.name) {
    return 1;
  }
  return 0;
});

In this example, the comparator function uses the less than (<) and greater than (>) operators to compare the name properties lexicographically. It returns -1 or 1 to determine the order of a and b respectively, or 0 if they are equal.

A Brief Note on Deeper String Sorting

It may not be obvious, but if you compare two string properties that start with the same letter (for example: 'car' and 'camera'), then the sort() method will continue to compare the subsequent characters in the strings to determine their lexicographic order.

Here's a quick rundown of how the comparison would work if two product names start with the same letter:

  1. The first characters of both strings (a.name and b.name) are compared.
  2. If the characters are the same (e.g., both are 'C'), the comparison moves to the next pair of characters.
  3. This process continues until a pair of characters differs.
  4. At the first difference, the string with the lower UTF16 code unit compares as less. If one string is an exact prefix of the other, the shorter string compares as less.

Dealing with Case Sensitivity

When sorting by string values, it is important to be aware that sorting by strings is casesensitive. The string 'Apple' will come before 'banana' here because uppercase 'A' has a lower UTF16 code unit than lowercase 'b'.

For a small set of simple labels, one way to ignore case is to compare lowercase copies within the comparator:

products.sort((a, b) => {
  const nameA = a.name.toLowerCase();
  const nameB = b.name.toLowerCase();

  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }
  return 0;
});

Lowercasing these values does not change the stored names, but it is not a universal languageaware comparison. For names or translated text, use localeCompare() or Intl.Collator with the intended locale and sensitivity. For example, a.name.localeCompare(b.name, "en", { sensitivity: "accent" }) ignores case whilst retaining accent distinctions in English.


The Wrap‑up

Sorting an array of objects requires a comparator function tailored to the specific property or properties you want to sort (and how). Whether dealing with numeric values, strings, or even more complex data structures, the comparator function is key to ensuring your objects are sorted in the desired order.

By understanding how to craft these functions, you can harness the full power of the Array.prototype.sort() method to organise your data structures effectively and avoid any weirdness that otherwise comes from lexicographic sorting!


Looking for technical direction?

I support teams that need senior judgement on React, Next.js, headless CMS architecture, performance, migrations, and technical SEO.