Overview
Most sorting in professional development involves arrays of objects, such as JSON data from a database, rather than simple numbers or strings. This article explains how to sort an entire array based on a specific property inside an object, such as an ID, name, or date.
Specifications (Input/Output)
Object Array Sorting Logic
To sort objects, you extract the properties you want to compare inside the comparison function (a, b) used by the sort method.
| Target | Code Example (Ascending) | Explanation |
| Numeric Property | (a, b) => a.id – b.id | Uses the result of subtraction (negative, zero, or positive). |
| String Property | (a, b) => a.name.localeCompare(b.name) | Uses the localeCompare method for dictionary order. |
- Input: An array containing objects.
- Output: An array sorted by a specific key (Note: This changes the original array).
Basic Usage
Sorting by ID (Numeric)
You access the id property from objects a and b and perform subtraction.
const users = [
{ id: 3, name: 'Tree' },
{ id: 1, name: 'Forest' }
];
// Ascending order (Smallest to Largest)
users.sort((a, b) => a.id - b.id);
console.log(users);
// Output: [{ id: 1, name: 'Forest' }, { id: 3, name: 'Tree' }]
Full Code (HTML / JAVASCRIPT)
This is a demo of a management screen where you can sort employee data by ID or by phonetic name (Furigana).
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Employee Directory Sort</title>
<style>
.directory-container {
font-family: 'Segoe UI', sans-serif;
max-width: 600px;
margin: 20px auto;
border: 1px solid #ccc;
border-radius: 8px;
padding: 20px;
background-color: #fcfcfc;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
button {
padding: 10px 15px;
cursor: pointer;
border: 1px solid #007bff;
background-color: #fff;
color: #007bff;
border-radius: 4px;
font-weight: bold;
}
button:hover, button.active {
background-color: #007bff;
color: #fff;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
text-align: left;
padding: 10px;
border-bottom: 1px solid #ddd;
}
th { background-color: #f0f0f0; color: #333; }
.id-col { width: 80px; text-align: center; }
.kana-col { color: #666; font-size: 0.85em; }
</style>
</head>
<body>
<div class="directory-container">
<h3>Employee Directory</h3>
<div class="controls">
<button id="sort-id">Sort by ID (1, 2...)</button>
<button id="sort-kana">Sort by Name (Phonetic)</button>
<button id="sort-desc">Sort by ID Descending (9, 8...)</button>
</div>
<table>
<thead>
<tr>
<th class="id-col">ID</th>
<th>Name</th>
<th>Phonetic (Kana)</th>
</tr>
</thead>
<tbody id="employee-list">
</tbody>
</table>
</div>
<script src="directory_sort.js"></script>
</body>
</html>
JavaScript
/**
* Employee Directory Sort Script
* Implementation of sorting logic for object arrays
*/
// 1. Employee Data (Array of Objects)
const employees = [
{ id: 104, name: 'Nakabayashi', kana: 'ナカバヤシ' },
{ id: 101, name: 'Mori', kana: 'モリ' },
{ id: 103, name: 'Kobayashi', kana: 'コバヤシ' },
{ id: 108, name: 'Oki', kana: 'オオキ' },
{ id: 102, name: 'Kogi', kana: 'オギ' },
{ id: 105, name: 'Omori', kana: 'オオモリ' }
];
// DOM elements
const tbody = document.getElementById('employee-list');
const btnSortId = document.getElementById('sort-id');
const btnSortKana = document.getElementById('sort-kana');
const btnSortDesc = document.getElementById('sort-desc');
/**
* Function to render the table
*/
const renderTable = () => {
tbody.innerHTML = '';
employees.forEach(emp => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td class="id-col">${emp.id}</td>
<td>${emp.name}</td>
<td class="kana-col">${emp.kana}</td>
`;
tbody.appendChild(tr);
});
};
/**
* Sort by ID Ascending (Numeric comparison)
*/
const sortById = () => {
employees.sort((a, b) => a.id - b.id);
updateActiveButton(btnSortId);
renderTable();
};
/**
* Sort by ID Descending (Numeric comparison)
*/
const sortByIdDesc = () => {
employees.sort((a, b) => b.id - a.id);
updateActiveButton(btnSortDesc);
renderTable();
};
/**
* Sort by Phonetic Name (String comparison)
*/
const sortByKana = () => {
employees.sort((a, b) => {
// Use localeCompare for dictionary order
return a.kana.localeCompare(b.kana, 'ja');
});
updateActiveButton(btnSortKana);
renderTable();
};
/**
* Helper function to update button styles
*/
const updateActiveButton = (activeBtn) => {
[btnSortId, btnSortKana, btnSortDesc].forEach(btn => btn.classList.remove('active'));
activeBtn.classList.add('active');
};
// Initial render
renderTable();
// Event listeners
btnSortId.addEventListener('click', sortById);
btnSortKana.addEventListener('click', sortByKana);
btnSortDesc.addEventListener('click', sortByIdDesc);
Custom Points
Sorting Japanese Kanji names directly can lead to unexpected results because it follows character codes rather than dictionary order. It is best to include a phonetic property (like kana) and use localeCompare to sort by that. For date objects, you should convert the property to a timestamp using a.date.getTime() - b.date.getTime() before subtracting.
Important Notes
Always ensure the property exists before comparing. If a property like a.kana is undefined or null, it can cause errors or unexpected ordering. You should use a guard clause to replace missing values with an empty string. Also, do not mix strings and numbers in properties like ID. If the data is mixed, convert them using Number(a.id) within the comparison function to ensure consistency.
Advanced Usage
Multiple Sort Conditions
You can sort by a primary property and then use a secondary property if the primary values are equal. For example, sorting by department code first and then by rank within the same department.
employees.sort((a, b) => {
// 1. Compare by department ID first
if (a.deptId !== b.deptId) {
return a.deptId - b.deptId;
}
// 2. If department IDs are equal, compare by rank
return a.rank - b.rank;
});
Summary
Sorting an array of objects is easy to control once you understand the pattern of the comparison function. You can handle any business data by using subtraction for numbers and the localeCompare method for strings. By mastering these two basic patterns and combining them for multiple conditions, you can efficiently manage data presentation in your JavaScript applications.
