Un tableau de nombres trié par sort sans précaution donne [1, 10, 100, 9]. Ce n'est pas un bug, c'est le comportement documenté, et c'est probablement le piège le plus rencontré du langage.
Deux choses sont à savoir avant d'écrire un tri : sort modifie le tableau d'origine, et il compare du texte tant qu'on ne lui dit pas comment comparer.
Définition
sort réordonne les éléments d'un Array (tableau) sur place et rend ce même tableau, pas une copie. Sans argument, chaque élément est converti en chaîne de caractères, puis les chaînes sont comparées caractère par caractère.
const notes = [10, 9, 1, 100];
console.log(notes.sort()); // [ 1, 10, 100, 9 ]
console.log(notes); // le tableau d'origine a été modifié
console.log([10, 9, 1, 100].sort((a, b) => a - b)); // [ 1, 9, 10, 100 ]« 10 » vient avant « 9 » pour la même raison que « ab » vient avant « b » dans un dictionnaire : le premier caractère décide. La fonction de comparaison rétablit l'ordre attendu.
La fonction de comparaison
Elle reçoit deux éléments et rend un nombre. Son signe seul compte, la valeur exacte n'a aucune importance.
- Négatif le premier élément passe avant le second.
- Zéro les deux gardent leur ordre relatif.
- Positif le second passe avant le premier.
const produits = [
{ nom: "Clavier", prix: 89 },
{ nom: "Souris", prix: 29 },
{ nom: "Écran", prix: 249 },
];
produits.sort((a, b) => a.prix - b.prix);
console.log(produits.map((p) => p.nom)); // [ 'Souris', 'Clavier', 'Écran' ]
produits.sort((a, b) => b.prix - a.prix); // du plus cher au moins cherInverser a et b inverse le tri, ce qui évite d'appeler reverse derrière.
Trier du texte, et trier sans modifier
Sur des mots accentués, la comparaison par défaut place « Zoé » avant « école », parce qu'elle compare des codes de caractères et non des lettres. localeCompare connaît les règles de la langue.
const mots = ["éclair", "avion", "zèbre", "École"];
console.log(mots.sort((a, b) => a.localeCompare(b, "fr")));
// [ 'avion', 'éclair', 'École', 'zèbre' ]
const original = [3, 1, 2];
const trie = [...original].sort((a, b) => a - b);
console.log(original); // [ 3, 1, 2 ], intactCopier avec Spread (...) avant de trier est le réflexe à prendre dès qu'une donnée est affichée ailleurs. La méthode toSorted, plus récente, fait la même chose en une seule étape et laisse l'original intact.
Questions fréquentes
Pourquoi [10, 9, 1] devient-il [1, 10, 9] ?
Parce que sans fonction de comparaison, les nombres sont convertis en texte avant d'être comparés. « 10 » commence par le caractère « 1 », qui vient avant « 9 ». Passer (a, b) => a - b règle définitivement la question pour des nombres.
Le tri est-il stable ?
Oui. Deux éléments jugés égaux par la comparaison conservent leur ordre d'origine, et c'est garanti par la norme depuis 2019. Cela permet de trier en deux passes : d'abord par nom, ensuite par prix, et les prix égaux resteront classés par nom.
Comment trier sur plusieurs critères à la fois ?
En enchaînant les comparaisons avec l'opérateur ||, qui passe au critère suivant quand le précédent rend zéro : (a, b) => a.prix - b.prix || a.nom.localeCompare(b.nom, "fr"). Les tris de listes, de tableaux de bord et de catalogues sont travaillés en détail dans la formation JavaScript.