# The Basics of Sorting in JavaScript

## Sorting Defaults
By default, the `sort()` method in JavaScript will sort an array ***in place*** and works by looping through each item in the array and comparing each item two at a time until the array is sorted. To do this, it converts the array to strings and sorts them *alphabetically in ascending order*. This will only work well if there is a simple array of case-insensitive strings. For 99% of the time, you will need to write a custom compare function.


## Compare Function
- If a compare function is supplied, all *non-undefined* array elements are sorted according to the return value of the compare function (negative, zero, positive) value.
    - All `undefined` elements are sorted to the end of the array, with no call to the compare function.
- If `a` and `b` are two elements being compared, then
   - If the result is negative `a` is sorted before `b`.
   - If the result is positive `b` is sorted before `a`.
- If the result is 0 leave `a` and `b` unchanged with respect to each other but sorted with respect to all different elements.
- It should be noted that you don't have to return -1 and 1 specifically. As long as one value is negative and one value is positive (greater than 0) it will still work. (However, you do need to specifically return 0 to represent equality between the items being compared.)

```
const compare = (a, b) => {  
   if (a < b) return -1;  
   if (a > b) return 1;  
   return 0; // a must be equal to b
}
```

## Sort By Numbers
This is by far the simplest and most succinct of all the sorting method types so providing a code example should explain itself.
```
const sortByNumbersAsc = (a, b) => a - b //Ascending sort
const sortByNumbersDesc = (a, b) => b - a //Descending sort
```

## Sort By Strings
Typically you will convert the strings you want to compare to a common case so use `toLowerCase()` or `toUpperCase()`. Whatever suits your fancy. 
 
[Good article on sorting Strings](https://www.digitalocean.com/community/tutorials/js-array-sort-strings) 
```
//Ascending String sort
const sortByStringAsc = (a,b) => {  
   const aLower = a.toLowerCase();  
   const bLower = b.toLowerCase();  
   return aLower > bLower ? 1 : bLower > aLower ? -1 : 0;
}

//Descending String sort
const sortByStringDesc = (a,b) => {  
   const aLower = a.toLowerCase();  
   const bLower = b.toLowerCase();  
   return aLower > bLower ? -1 : bLower > aLower ? 1 : 0;
}
```


## Sort Array of Objects
This is probably the most realistic way you will need to sort. Thankfully it’s not that much different from sorting a String or Number. Actually, it’s pretty much the same except instead of just the generic `a` & `b` comparison, you will need to explicitly state which object properties you want to compare against.
```
const cars = [  
{ make: "Nissan", year: 2017 },  
{ make: "Chevrolet", year: 2001 }, 
{ make: "BMW", year: 2010 }
];    

//Numeric sort - sort by year ascending
cars.sort((a,b) => a.year - b.year) 

//String sort - sort by car make 🚗  ascending
const sortByStringAsc = (a,b) => {  
   const aMake = a.make.toLowerCase();  
   const bMake = b.make.toLowerCase();  
   return aMake > bMake ? 1 : bMake > aMake ? -1 : 0;
}
```

## Descending Sort
I've provided examples of descending sorts in the respective code blocks but I wanted to write a little blurb about this as well. 

If you need to sort in descending order, just swap the `return 1` in the comparison function with `return -1` for both `a` & `b` conditionals. Or put another way, it’s basically the reverse of the ascending sort logic. 

Another way I’ve seen suggested to sort in descending order is to use the  [`reverse()` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse).


## Gotchas
Because the `sort()` method sorts an array ***in place***,  it will directly manipulate the array that is being sorted, therefore making it mutable 👎🏽. Due to this, you want to make sure you are working off of a ***copy of the array*** or using a package like [immer](https://immerjs.github.io/immer/docs/introduction) to keep things  [immutable](https://en.wikipedia.org/wiki/Immutable_object).

### Resources
-  [W3 Schools - Array Sort](https://www.w3schools.com/js/js_array_sort.asp) 
- [ MDN - Array Sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 
-  [javascript.info - Array Sort](https://javascript.info/array-methods#sort-fn) 

*[Photo by  [UX Indonesia](https://unsplash.com/@uxindo?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on  [Unsplash](https://unsplash.com)]*
