JavaScript Array Sort Method and its gotchas - Explained with Examples

JavaScript Array Sort Method and its gotchas - Explained with Examples

Featured on Hashnode

In this article, we will see how to properly use the array sort method and learn common gotchas associated with it.

Want to learn Redux in detail and build a complete food ordering app? check out my Mastering Redux course. Following is the preview of the app, we'll be building in the course. It's a great project you can add to your portfolio/resume.

Note that, in this app, I have used INR as the currency for displaying the prices but you can easily change it to USD or AUD or any other currency with a single configuration change in the app.


Let's get started

The Array sort method sorts an array regardless of its data type - whether it's a numbered array, string array, or complex array of objects.

The sort method has the following syntax:

array.sort([compareFunction])

Here, the compareFunction is optional.

One thing you need to remember is that the Array sort method does not return a new sorted array, but instead changes the original array.

const months = ["Nov", "Feb", "Jan", "Dec" ];
const sorted = months.sort(); // sort the original array and return reference to it

console.log(months); // ["Dec", "Feb", "Jan", "Nov"]
console.log(sorted); // ["Dec", "Feb", "Jan", "Nov"]

Here's a Code Pen Demo.

If you compare the months and sorted variables using ===, you can see that they point to the same array which is the original sorted array.

This is a very famous interview question to check if the candidate knows the array sort method.

If you don’t want to change the original array, you can add a slice method before the sort method.

The slice method returns a new shallow copy of an array.

const months = ["Nov", "Feb", "Jan", "Dec" ];
const sorted = months.slice().sort(); // returns a new sorted array

console.log(months); // ["Nov", "Feb", "Jan", "Dec"]
console.log(sorted); // ["Dec", "Feb", "Jan", "Nov"]
console.log(months === sorted); // false

Here's a Code Pen Demo.

By default, the sort method sorts an array as strings.

This is fine in the case of strings that are sorted alphabetically, but it produces incorrect results when we sort numbers.

const numbers = [100, 25, 1, 5 ];
const sorted = numbers.slice().sort(); // returns a new sorted array
console.log(numbers); // [100, 25, 1, 5 ]
console.log(sorted); // [1, 100, 25, 5]

Here's a Code Pen Demo.

As you can see in the sorted array, 5 comes last and 100 comes before 25 even though 100 is larger than 25 and 5.

This is because when sorting numbers, each number is converted to a string. The sort method compares character by character, so the 1 in 100 is smaller than the 2 in 25 so while sorting in ascending order, 100 comes before 25.

This is a very common gotcha programmers usually forget.

We can fix it by passing the compare function to the sort method.

const numbers = [100, 25, 1, 5];
const sorted = numbers.slice().sort(function(a, b) { 
 return a - b; 
}); // returns a new sorted array

console.log(numbers); // [100, 25, 1, 5]
console.log(sorted); // [1, 5, 25, 100]

Here's a Code Pen Demo.

When comparing 100 and 25, the sort() method calculates 100 - 25 as 75 which is a positive value so it puts 25 before 100.

This will sort the array in ascending order.

To sort in descending order, we need to make a small change in the compare function.

const numbers = [100, 25, 1, 5];
const sorted = numbers.slice().sort(function(a, b) { 
 return b - a; 
}); // returns a new sorted array

console.log(numbers); // [100, 25, 1, 5]
console.log(sorted); // [100, 25, 5, 1]

Here, we've used b - a instead of a - b to sort in descending order.

Here's a Code Pen Demo.

So always pass the compare function when sorting numbers otherwise you will get an undesired result.

Rules that sort function uses while sorting

  1. If the first value is alphabetically before the second value, a negative value is returned.
  2. If the first value is alphabetically after the second value, a positive value is returned.
  3. If the first and second value is equal, zero is returned.

Now, let’s write a code that will sort the users by their last name.

const users = ["David Jonhnson", "Tim Lindholm", "David Beckham", "Johnny Depp" ];
const sorted = users.slice().sort(function(firstUser, secondUser) { 
 const firstLastName = firstUser.split(" ")[1];
 const secondLastName = secondUser.split(" ")[1];

 if(firstLastName < secondLastName) return -1;
 if(firstLastName > secondLastName) return 1;
 return 0;
});

console.log(users); // ["David Jonhnson", "Tim Lindholm", "David Beckham", "Johnny Depp"]
console.log(sorted); // ["David Beckham", "Johnny Depp", "David Jonhnson", "Tim Lindholm"]

Here's a Code Pen Demo.

To sort an array in random order (shuffle), we can use the Math.random method

const numbers = [100, 25, 1, 5 ];
const sorted = numbers.slice().sort(function(a, b) { 
 return 0.5 - Math.random() 
}); // returns a new sorted array

console.log(numbers); // [100, 25, 1, 5]
console.log(sorted); // array in random order

Sorting an array of objects

Consider we have an array of user objects where each user object consists of a name and age property, and we want to sort the array based on the users' age in ascending order. We can do it as below:

const users = [
    {
      name: 'David',
      age: 30
    },
    {
      name: 'Mike',
      age: 40
    },
    {
      name: 'John',
      age: 25
    }
];

const sorted = users.slice().sort(function(firstUser, secondUser) { 
 if(firstUser.age < secondUser.age) return -1;
 if(firstUser.age > secondUser.age) return 1;
 return 0;
});

console.log(users); // [{'name':'David','age':30},{'name':'Mike','age':40},{'name':'John','age':25}]
console.log(sorted); // [{'name':'John','age':25},{'name':'David','age':30},{'name':'Mike','age':40}]

Here's a Code Pen Demo.

To sort the array in descending order of age:

const users = [
    {
      name: 'David',
      age: 30
    },
    {
      name: 'Mike',
      age: 40
    },
    {
      name: 'John',
      age: 25
    }
];


const sorted = users.slice().sort(function(firstUser, secondUser) { 
 if(firstUser.age < secondUser.age) return 1;
 if(firstUser.age > secondUser.age) return -1;
 return 0;
});

console.log(users); // [{'name':'David','age':30},{'name':'Mike','age':40},{'name':'John','age':25}]
console.log(sorted); // [{'name':'Mike','age':40},{'name':'David','age':30},{'name':'John','age':25}]

Here's a Code Pen Demo.

Thanks for reading!

Want to learn all ES6+ features in detail including let and const, promises, various promise methods, array and object destructuring, arrow functions, async/await, import and export and a whole lot more from scratch?

Check out my Mastering Modern JavaScript book. This book covers all the pre-requisites for learning React and helps you to become better at JavaScript and React.

Check out free preview contents of the book here.

Also, you can check out my free Introduction to React Router course to learn React Router from scratch.

Want to stay up to date with regular content regarding JavaScript, React, Node.js? Follow me on LinkedIn.

Did you find this article valuable?

Support Yogesh Chavan by becoming a sponsor. Any amount is appreciated!