Skip to main content

How to Sort an Array with null or undefined Values Coming Lasts in JavaScript

When you sort an array in JavaScript that contains null or undefined values, the default Array.prototype.sort() method can produce surprising and often undesirable results. undefined values are pushed to the end, but null is coerced to the string "null", causing it to be sorted alphabetically among other strings.

To achieve a predictable and clean sort where all valid data comes first, you must provide a custom comparison function to the sort() method. This guide will teach you how to write a robust comparator that correctly handles null and undefined, ensuring they are always pushed to the end of the sorted array.

The Core Problem: Default sort() Behavior with null and undefined

The default sort() method converts elements to strings before comparing them. This leads to two different behaviors for null and undefined:

  • null is converted to the string "null".
  • undefined values are grouped together and sent to the end.

Example of the problem:

// Problem: The default sort is unpredictable and messy.
const data = ['cat', undefined, 'dog', null, 'ant', 'zebra'];
data.sort();

console.log(data);

Output: null is sorted as the string "null", placing it in the middle.

['ant', 'cat', 'dog', null, 'zebra', undefined]

For most use cases, we want all the "empty" values (null and undefined) grouped together at the end.

The Solution: A Custom Comparison Function

To control the sort order, we must provide a comparison function to sort(). This function explicitly tells sort() how to handle null and undefined values.

The comparison function (a, b) should return:

  • A positive number (1) to sort b before a.
  • A negative number (-1) to sort a before b.
  • Zero (0) to keep their order unchanged.

Our logic will be:

  1. If a is null or undefined, it should always come after b. So, return 1.
  2. If b is null or undefined, it should always come after a. So, return -1.
  3. If neither is null or undefined, perform a standard comparison.

Solution:

const data = ['cat', undefined, 'dog', null, 'ant', 'zebra'];

// Sort in ascending order, with nulls and undefineds last.
data.sort((a, b) => {
if (a == null) return 1; // a is null/undefined, so b comes first
if (b == null) return -1; // b is null/undefined, so a comes first
return a.localeCompare(b); // Regular string comparison for valid values
});

console.log(data);

Output:

['ant', 'cat', 'dog', 'zebra', null, undefined]

How the Comparison Logic Works

This custom comparator effectively creates two groups in the array: the valid data and the "empty" values.

  • if (a == null) return 1;: When sort() compares a valid string (b) to an empty value (a), this rule says "a is greater than b," which forces all null and undefined values towards the end of the array.
  • if (b == null) return -1;: When sort() compares an empty value (b) to a valid string (a), this rule says "a is less than b," which also forces the empty value (b) towards the end.
  • return a.localeCompare(b);: Once the null/undefined checks have passed, we know we are comparing two valid strings, so we can proceed with a standard, reliable string comparison.
note

A Note on null == undefined: This solution deliberately uses the loose equality operator (==). The condition a == null is true for both null and undefined, which allows us to handle both cases with a single line of code.

For a more practical and reusable solution, you can create a single function that handles both ascending and descending order for numbers or strings.

/**
* Sorts an array with null/undefined values placed at the end.
* @param {Array} arr The array to sort.
* @param {'asc' | 'desc'} order The desired sort order for non-null values.
*/
function sortWithNullsLast(arr, order = 'asc') {
// Create a shallow copy to avoid mutating the original array
const sorted = [...arr];

sorted.sort((a, b) => {
if (a == null) return 1;
if (b == null) return -1;

// Perform the actual sort for non-null values
const orderMultiplier = (order === 'desc') ? -1 : 1;

if (typeof a === 'string' && typeof b === 'string') {
return a.localeCompare(b) * orderMultiplier;
}

// Fallback for numbers or other types
if (a < b) return -1 * orderMultiplier;
if (a > b) return 1 * orderMultiplier;
return 0;
});

return sorted;
}

// Example Usage:
const data = ['c', undefined, 'z', 'b', null, 'a'];
const sortedAsc = sortWithNullsLast(data, 'asc');
const sortedDesc = sortWithNullsLast(data, 'desc');

console.log(sortedAsc); // Output: ['a', 'b', 'c', 'z', null, undefined]
console.log(sortedDesc); // Output: ['z', 'c', 'b', 'a', null, undefined]

A Note on Mutability

The Array.prototype.sort() method sorts an array in place, meaning it mutates (modifies) the original array. This is often undesirable.

Recommended Best Practice: Always create a shallow copy of the array before sorting it if you want to preserve the original. The easiest way to do this is with the spread syntax (...), as shown in the reusable function above.

const originalArray = ['c', null, 'a'];

// Create a copy before sorting to preserve the original.
const sortedArray = [...originalArray].sort(/* ... */);

Conclusion

To correctly sort an array with null or undefined values in JavaScript, you must provide a custom comparison function to the sort() method.

  • The default sort() method is unreliable for this task because it coerces null to the string "null".
  • The recommended best practice is to create a comparator that explicitly checks for null/undefined and pushes them to the end by returning 1 or -1 accordingly.
  • The condition if (a == null) is a convenient way to handle both null and undefined at the same time.
  • Always create a copy of your array (e.g., with [...arr]) before sorting to avoid mutating the original data.