
Sorting Complex Arrays in JavaScript

Sorting arrays and manipulating data in JavaScript is a common, often complex and difficult, part of the work we do as front‑end and full‑stack developers. When working with complex data structures in particular, it requires a deeper understanding of how the sort() method behaves. Sorting arrays with objects, nested properties, or multiple criteria can be tricky, but JavaScript provides powerful tools to handle these scenarios effectively, as long as we understand how to properly use them...
Here, I will explore different techniques for sorting complex arrays in JavaScript, covering common use cases and best practices. By the end, you should have a strong grasp of how to manipulate and organise data efficiently.
Understanding the sort() Method
JavaScript's built‑in Array.prototype.sort() method sorts elements in place and, by default, converts those elements to strings before comparing them. However, this behaviour is not nearly as useful if you are working with numbers or objects.
Basic Sorting with Numbers
Sorting a simple array of numbers might seem straightforward, however, JavaScript's sort() method does not handle numbers as you might expect by default. Let's start with an example:
const numbers = [10, 5, 8, 1, 7];numbers.sort();console.log(numbers); // Output: [1, 10, 5, 7, 8] (incorrect sorting)What I'm demonstrating here is the classic issue that sort() presents by default, 10 comes before 5 because sort() converts the elements passed to it to strings before comparing them. In fact, if we added another value like 101 to the array, even that would be placed before 5 when using sort() in it's default configuration.
In order to use sort() to correct sort numbers, we need to use it as a higher‑order function and pass a comparison function into it. Like this:
numbers.sort((a, b) => a - b);console.log(numbers); // Output: [1, 5, 7, 8, 10] (correct sorting)The comparison function ensures numeric sorting by subtracting b from a. A negative return value means a should come before b, a positive value means b should come before a, and 0 keeps the order unchanged.
Sorting an Array of Objects
When dealing with an array of objects, it becomes a little more complicated; we must specify which property to sort by in our comparison:
const people = [ { name: "Maddie", age: 25 }, { name: "Bob", age: 30 }, { name: "Charlie", age: 20 }];people.sort((a, b) => a.age - b.age);console.log(people);// Output: [{ name: "Charlie", age: 20 }, { name: "Maddie", age: 25 }, { name: "Bob", age: 30 }]In this way, the array is sorted in ascending order based on the age property.
Sorting Nested Properties
When we're dealing with deeply nested properties, we handle them in much the same way, but just by making sure that reference the correct nested property within the comparison function.
For example, if we have a nested dataset of devices and want to sort them by their price, it would look like this:
const products = [ { name: "Laptop", details: { price: 1000 } }, { name: "Phone", details: { price: 700 } }, { name: "Tablet", details: { price: 500 } }];products.sort((a, b) => a.details.price - b.details.price);Really, this is much the same as the example above, we've just moved one level further down the nested data tree.
Sorting by Multiple Criteria
In some cases, sorting by a single property just simply isn't enough. For example, we may need to sort by age, but if two people have the same age, we also want to sort them alphabetically by name. I came across a similar requirement in sorting search results for Virgin Atlantic, where two flights leaving at the same time should also be sorted by the airline name.
Sticking with the people‑and‑age example for consistently, here's how we would handle this multi‑criteria sorting:
people.sort((a, b) => { if (a.age === b.age) { return a.name.localeCompare(b.name); // Sort alphabetically } return a.age - b.age; // Sort by age first});This creates a stable sort where records with the same primary sorting key (age) are ordered by a secondary key (name), once sorted by age.
Case‑Insensitive String Sorting
Sorting by Unicode Value
A final 'complex sorting' example for today, and another quirk of string‑based sorting. By default, string sorting in JavaScript is case‑sensitive. This is because JavaScript uses unicode values when comparing strings, and uppercase letters (A‑Z) have lower unicode values than lowercase letters (a‑z).
If, for example, we had Cat, cat, dog, and Dog in an array, then when sorted, the strings would come back in the order ["Car", "Dog", "car", "dog"]:
const words = ["cat", "Cat", "dog", "Dog"];words.sort();console.log(words); // Output: ["Cat", "Dog", "cat", "dog"]This is because the unicode values for the first letter of each word are:
C
=U+0043D
=U+0044c
=U+0063d
=U+0064
In my experience, this trips up developers all the time, although hopefully it makes sense once you see it in action as above.
Sorting Without Case Sensitivity
Since sorting is based on Unicode values, we need to convert the elements of our array to the same case before attempting to compare them. Usually, this we use localeCompare() combined with toLowerCase() like this:
const words = ["banana", "Apple", "cherry"];words.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));console.log(words); // Output: ["Apple", "banana", "cherry"]Given what we've discussed above about sorting by unicode, then often simply converting the elements to lowercase for the sake of comparison is enough to standardise our input. However, combining this with localeCompare() makes sure that proper sorting occurs across different languages and handles more locale‑specific rules, which might otherwise fall outside of a simple character comparison.
To offer an example, in the Swedish alphabet ä comes after z, whereas in English, it could be treated as a variation of a and therefore fall immediately after it in sorting.
So, if we use localeCompare set to sv too, we get this:
const words = ["äpple", "apple", "banana"];words.sort((a, b) => a.localeCompare(b, "sv"));console.log(words); // Output: ["apple", "banana", "äpple"]Without using localeCompare() the sorting would be wrong: ["apple", "äpple", "banana"].
Wrapping up
Sorting complex arrays in JavaScript requires a solid grasp of the sort() method and how to use comparison functions effectively. By default, JavaScript sorts elements as strings using their unicode values, which can lead to unexpected results when working with numbers or mixed‑case text.
We've also explored how JavaScript's default sorting behaviour is case‑sensitive and how localeCompare() provides a more robust approach, particularly when working with international character sets. Understanding these nuances allows for more reliable and maintainable sorting operations. Whether you're sorting numbers, objects, or nested properties, knowing how to structure your sorting logic is essential. Whether working with numbers, objects, or nested properties, structuring sorting logic correctly ensures predictable and efficient data handling.
Key Takeaways
- JavaScript's
sort()method sorts elements as strings by default, based on Unicode values, which can lead to unexpected results. - Sorting numbers requires explicit subtraction (
a ‑ b) to ensure correct numerical ordering. - Object sorting relies on accessing the correct property and handling nested structures where necessary.
- Multi‑criteria sorting enables prioritisation when sorting by multiple fields.
- Using
localeCompare()ensures case‑insensitive sorting and handles locale‑specific character rules correctly. - Understanding default sorting behaviour helps prevent unexpected results and ensures predictable data handling.
Sorting is a core part of working with arrays in JavaScript, and refining these techniques will help in structuring data efficiently across different applications.
- Always provide a comparison function when sorting numbers.
- Sorting objects requires specifying which property to compare.
- Multi‑criteria sorting allows for prioritised ordering of values.
- Use
localeCompare()for proper case‑insensitive sorting. - Sorting nested properties requires carefully accessing the correct value before comparison.
Having a clear understanding of these sorting techniques will help you write more reliable and structured JavaScript code, ensuring your data is consistently organised.
Related Articles

Understanding the Backtracking Approach: Solving the 'Word Search' Problem. 
Sorting Objects in JavaScript. Sorting Objects in JavaScript

Understanding JavaScript's sort() Method. Understanding JavaScript's
sort()Method
Reduce() in JavaScript. reduce()in JavaScript
Default Parameters in JavaScript: A Guide. Default Parameters in JavaScript: A Guide

Dynamic Navigation with React Router. Dynamic Navigation with React Router

Automatically Deploy a Static Gatsby Site via FTP. Automatically Deploy a Static Gatsby Site via FTP

Exploring the Liquid Templating Language. Exploring the Liquid Templating Language

Object.freeze(), Object.seal(), and preventExtensions(). Object.freeze(),Object.seal(), andpreventExtensions()
Understanding call, apply, and bind in JavaScript. Understanding
call,apply, andbindin JavaScript
Toggle a Boolean in JavaScript. Toggle a Boolean in JavaScript
Advanced Sass: Loops. Advanced Sass: Loops