frontend
Sort Array of Objects in JavaScript
January 24, 2026
Sort Array of Objects in JavaScript
Overview
Sorting arrays of objects is a common task in JavaScript. You can sort objects by one or multiple properties, in ascending or descending order, and handle various data types. The Array.sort() method with custom comparison functions is the primary tool for this.
Basic Sorting
const array = [
{ name: "John", age: 30 },
{ name: "Alice", age: 25 },
{ name: "Bob", age: 35 },
{ name: "Alice", age: 30 },
];
function sortArrayObjects(arr) {
return arr.sort((a, b) => {
// If names are different, sort by name
if (a.name !== b.name) {
return a.name.toLowerCase().localeCompare(b.name);
} else {
// If names are the same, sort by age
return a.age - b.age;
}
});
}
console.log(sortArrayObjects(array));
// Result: Sorted by name (ascending), then by age (ascending) for same names
Single Property Sorting
Sort by String Property (Ascending)
const users = [
{ name: "John", age: 30 },
{ name: "Alice", age: 25 },
{ name: "Bob", age: 35 }
];
// Sort by name (ascending)
users.sort((a, b) => a.name.localeCompare(b.name));
Sort by Number Property (Ascending)
// Sort by age (ascending)
users.sort((a, b) => a.age - b.age);
Sort by Number Property (Descending)
// Sort by age (descending)
users.sort((a, b) => b.age - a.age);
Multi-Property Sorting
function sortByMultipleProperties(arr, properties) {
return arr.sort((a, b) => {
for (const prop of properties) {
const { key, order = 'asc' } = typeof prop === 'string'
? { key: prop, order: 'asc' }
: prop;
if (a[key] < b[key]) {
return order === 'asc' ? -1 : 1;
}
if (a[key] > b[key]) {
return order === 'asc' ? 1 : -1;
}
}
return 0;
});
}
// Usage
const sorted = sortByMultipleProperties(array, [
{ key: 'name', order: 'asc' },
{ key: 'age', order: 'desc' }
]);
Advanced Sorting Functions
Generic Sort Function
function sortObjects(arr, sortConfig) {
return arr.sort((a, b) => {
for (const config of sortConfig) {
const { key, order = 'asc', type = 'auto' } = config;
let aVal = a[key];
let bVal = b[key];
// Handle null/undefined
if (aVal == null && bVal == null) continue;
if (aVal == null) return 1;
if (bVal == null) return -1;
// Type-specific comparison
let comparison = 0;
if (type === 'number' || (type === 'auto' && typeof aVal === 'number')) {
comparison = aVal - bVal;
} else if (type === 'date' || (type === 'auto' && aVal instanceof Date)) {
comparison = aVal.getTime() - bVal.getTime();
} else {
comparison = String(aVal).localeCompare(String(bVal));
}
if (comparison !== 0) {
return order === 'asc' ? comparison : -comparison;
}
}
return 0;
});
}
Case-Insensitive String Sorting
function sortByStringCaseInsensitive(arr, key) {
return arr.sort((a, b) => {
return a[key].toLowerCase().localeCompare(b[key].toLowerCase());
});
}
Date Sorting
function sortByDate(arr, key) {
return arr.sort((a, b) => {
return new Date(a[key]) - new Date(b[key]);
});
}
Common Sorting Patterns
Pattern 1: Sort by Multiple Criteria
const products = [
{ name: "Laptop", price: 1000, rating: 4.5 },
{ name: "Phone", price: 800, rating: 4.8 },
{ name: "Tablet", price: 600, rating: 4.5 }
];
// Sort by rating (desc), then by price (asc)
products.sort((a, b) => {
if (a.rating !== b.rating) {
return b.rating - a.rating; // Descending
}
return a.price - b.price; // Ascending
});
Pattern 2: Custom Sort Order
const statusOrder = { 'pending': 1, 'processing': 2, 'completed': 3, 'cancelled': 4 };
const orders = [
{ id: 1, status: 'completed' },
{ id: 2, status: 'pending' },
{ id: 3, status: 'processing' }
];
orders.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]);
Pattern 3: Nested Property Sorting
const users = [
{ name: "John", address: { city: "New York", zip: 10001 } },
{ name: "Alice", address: { city: "Boston", zip: 02101 } }
];
users.sort((a, b) => {
return a.address.city.localeCompare(b.address.city);
});
Immutable Sorting
// Create a new sorted array without mutating original
function sortImmutable(arr, compareFn) {
return [...arr].sort(compareFn);
}
const sorted = sortImmutable(users, (a, b) => a.age - b.age);
Performance Considerations
For Large Arrays
// Use indexed sorting for better performance
function sortLargeArray(arr, key) {
// Create index array
const indices = arr.map((_, i) => i);
// Sort indices based on values
indices.sort((a, b) => {
const aVal = arr[a][key];
const bVal = arr[b][key];
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
});
// Return sorted array
return indices.map(i => arr[i]);
}
Real-World Examples
Example 1: E-commerce Product Sorting
const products = [
{ name: "Laptop", price: 1000, inStock: true, rating: 4.5 },
{ name: "Phone", price: 800, inStock: false, rating: 4.8 },
{ name: "Tablet", price: 600, inStock: true, rating: 4.2 }
];
// Sort: in stock first, then by rating, then by price
products.sort((a, b) => {
// In stock items first
if (a.inStock !== b.inStock) {
return b.inStock - a.inStock;
}
// Higher rating first
if (a.rating !== b.rating) {
return b.rating - a.rating;
}
// Lower price first
return a.price - b.price;
});
Example 2: User List Sorting
const users = [
{ name: "John", role: "admin", lastLogin: new Date("2024-01-15") },
{ name: "Alice", role: "user", lastLogin: new Date("2024-01-20") },
{ name: "Bob", role: "admin", lastLogin: new Date("2024-01-10") }
];
// Sort: admins first, then by last login (most recent first)
users.sort((a, b) => {
const roleOrder = { admin: 1, user: 2 };
if (roleOrder[a.role] !== roleOrder[b.role]) {
return roleOrder[a.role] - roleOrder[b.role];
}
return b.lastLogin - a.lastLogin;
});
Utility Functions
Reusable Sort Function
class ArraySorter {
static by(key, order = 'asc') {
return (a, b) => {
const aVal = a[key];
const bVal = b[key];
if (aVal < bVal) return order === 'asc' ? -1 : 1;
if (aVal > bVal) return order === 'asc' ? 1 : -1;
return 0;
};
}
static byMultiple(config) {
return (a, b) => {
for (const { key, order = 'asc' } of config) {
const comparison = this.by(key, order)(a, b);
if (comparison !== 0) return comparison;
}
return 0;
};
}
}
// Usage
users.sort(ArraySorter.by('age', 'desc'));
users.sort(ArraySorter.byMultiple([
{ key: 'name', order: 'asc' },
{ key: 'age', order: 'desc' }
]));
Best Practices
- Use localeCompare for Strings: Handles internationalization correctly
- Handle Null/Undefined: Check for null/undefined values before sorting
- Immutable Sorting: Create new arrays if you need to preserve original
- Type Safety: Ensure consistent data types for reliable sorting
- Performance: Consider indexed sorting for very large arrays
- Case Sensitivity: Use toLowerCase() for case-insensitive string sorting
Common Mistakes
Mistake 1: Not Returning Numbers
// ❌ Wrong
arr.sort((a, b) => a.age > b.age);
// ✅ Correct
arr.sort((a, b) => a.age - b.age);
Mistake 2: Mutating Original Array
// ❌ Mutates original
const sorted = arr.sort((a, b) => a.age - b.age);
// ✅ Creates new array
const sorted = [...arr].sort((a, b) => a.age - b.age);
Mistake 3: Not Handling Null Values
// ❌ May cause errors
arr.sort((a, b) => a.property - b.property);
// ✅ Handles null
arr.sort((a, b) => {
if (a.property == null) return 1;
if (b.property == null) return -1;
return a.property - b.property;
});