Tableaux et objets
Cours · JavaScript : rendre le Web interactif (école d'ingénieur), chapitre 5 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun
La Librairie du Campus manipule sans cesse des collections : la liste des livres du catalogue, les lignes d'un panier, les rayons, les auteurs. Et chaque livre est lui-même un petit paquet de données : un titre, un auteur, un rayon, un prix. En Java, on aurait écrit une classe Livre et une ArrayList<Livre>. En JavaScript, on commence plus simplement : un tableau d'objets littéraux, écrits directement entre crochets et accolades, sans déclarer de type.
Ce chapitre présente ces deux structures et les outils qui les accompagnent : les méthodes de tableau qui remplacent la plupart des boucles (map, filter, reduce…), le tri et son comparateur, les objets et leurs propriétés, la déstructuration, les collections Map et Set, et le format JSON qui sert à échanger tout cela avec un serveur. Il insiste sur une notion que Java connaît déjà mais qui surprend toujours : tableaux et objets sont manipulés par référence.
Objectifs du chapitre
- Créer, lire et modifier un tableau ; le parcourir avec
for...of. - Transformer une collection avec
map,filter,find,some,reduce, et les enchaîner. - Trier correctement : comparateur numérique,
localeCompare, tri qui modifie ou non le tableau. - Créer et manipuler des objets littéraux ; distinguer référence et copie, copie superficielle et profonde.
- Utiliser la déstructuration, la décomposition
...,Map,Setet JSON.
Tous les programmes du chapitre sont dans code/ch5/ ; on les exécute avec Node.js :
$ node tableaux.mjs
Node affiche les tableaux et les objets sous une forme un peu différente de la console du navigateur (guillemets simples, espaces entre crochets), mais les valeurs sont les mêmes.
5.1 Les tableaux
Un tableau s'écrit entre crochets. Contrairement au tableau Java, il n'a pas de taille fixe ni de type d'élément : il grandit et rétrécit à la demande, comme une ArrayList.
const titres = ["Programmation Java", "Analyse MPSI", "Le Petit Prince"];
console.log(titres.length);
console.log(titres[0]);
console.log(titres.at(-1));
console.log(titres[5]);
titres.push("L’Étranger");
console.log(titres);
const retire = titres.shift();
console.log(retire, titres.length);
console.log(titres.includes("Analyse MPSI"), titres.indexOf("Physique"));
3
Programmation Java
Le Petit Prince
undefined
[
'Programmation Java',
'Analyse MPSI',
'Le Petit Prince',
'L’Étranger'
]
Programmation Java 3
true -1
lengthest une propriété (pas une méthode) ; les indices vont de 0 àlength - 1.at(-1)lit le dernier élément ; un indice négatif compte à partir de la fin.- Lire hors du tableau ne lève aucune exception : on obtient
undefined. Là où Java lançait uneArrayIndexOutOfBoundsException, JavaScript laisse l'erreur se propager silencieusement, souvent jusqu'à unTypeErrorplus loin. pushajoute à la fin,popretire le dernier ;unshiftetshiftfont de même au début.includesrépond par un booléen,indexOfdonne la position, ou .
Un tableau déclaré const se modifie
const titres = [...] interdit de réaffecter la variable titres à un autre tableau, pas de modifier le tableau lui-même : titres.push(...) est permis. C'est le final de Java : la référence est constante, l'objet ne l'est pas.
5.1.1 Parcourir
La boucle for...of donne chaque élément ; forEach appelle une fonction pour chaque élément, avec en second argument son indice.
const prix = [32, 89, 45, 59, 8.5, 7.9];
for (const p of prix) {
if (p > 50) {
console.log("cher :", p);
}
}
prix.forEach((p, i) => console.log(i, p));
cher : 89
cher : 59
0 32
1 89
2 45
3 59
4 8.5
5 7.9
On préfère for...of : on peut en sortir avec break ou return, et il fonctionnera avec await au chapitre 9. La boucle for...in, elle, parcourt les noms des propriétés d'un objet : sur un tableau, elle donne les indices sous forme de chaînes. Ne l'utilisez pas sur un tableau.
5.2 Transformer une collection
Au chapitre 4, nous avons vu qu'une fonction peut en recevoir une autre en argument. Les tableaux en tirent une famille de méthodes qui remplacent la plupart des boucles écrites à la main : on dit ce que l'on veut, pas comment le calculer. C'est l'équivalent des streams de Java (stream().map(...).filter(...)), sans stream() ni collect.
Chacune reçoit une fonction appelée avec l'élément (puis son indice) :
map(f): nouveau tableau desf(x), de même longueur ;filter(f): nouveau tableau des éléments pour lesquelsf(x)est vrai ;find(f): le premier élément qui convient, ouundefined;findIndex(f): sa position, ou ;some(f): au moins un convient ?every(f): tous conviennent ?reduce(f, initial): accumule une valeur unique, en appelantf(accumulateur, x).
Aucune de ces méthodes ne modifie le tableau d'origine.
const livres = [
{ titre: "Programmation Java", rayon: "Informatique", prix: 32 },
{ titre: "Introduction à l’algorithmique", rayon: "Informatique", prix: 89 },
{ titre: "Analyse MPSI", rayon: "Mathématiques", prix: 45 },
{ titre: "Le Petit Prince", rayon: "Littérature", prix: 8.5 },
];
const titres = livres.map((livre) => livre.titre);
console.log(titres);
const informatique = livres.filter((livre) => livre.rayon === "Informatique");
console.log(informatique.length);
const premierBonMarche = livres.find((livre) => livre.prix < 10);
console.log(premierBonMarche.titre);
console.log(livres.find((livre) => livre.prix > 100));
console.log(livres.some((livre) => livre.prix > 50), livres.every((livre) => livre.prix > 5));
console.log(livres.findIndex((livre) => livre.rayon === "Mathématiques"));
[
'Programmation Java',
'Introduction à l’algorithmique',
'Analyse MPSI',
'Le Petit Prince'
]
2
Le Petit Prince
undefined
true true
2
Les éléments du tableau livres sont des objets littéraux (section 5.4) ; livre.titre lit la propriété titre. Remarquez la recherche qui échoue : find rend undefined sans erreur, et c'est l'accès suivant, .titre, qui échouerait.
5.2.1 Accumuler une valeur
reduce est la plus générale : elle part d'une valeur initiale et la fait évoluer élément après élément. Le total d'un panier en est l'exemple type.
const panier = [
{ titre: "Programmation Java", prix: 32, quantite: 2 },
{ titre: "Le Petit Prince", prix: 8.5, quantite: 3 },
];
const total = panier.reduce((somme, ligne) => somme + ligne.prix * ligne.quantite, 0);
console.log(total);
const nombreDeLivres = panier.reduce((n, ligne) => n + ligne.quantite, 0);
console.log(nombreDeLivres);
// Chaînage : les titres des lignes de plus de 20 €, en majuscules.
const gros = panier
.filter((ligne) => ligne.prix * ligne.quantite > 20)
.map((ligne) => ligne.titre.toUpperCase());
console.log(gros);
89.5
5
[ 'PROGRAMMATION JAVA', 'LE PETIT PRINCE' ]
Déroulons le premier reduce : l'accumulateur vaut d'abord 0 ; après la première ligne, ; après la seconde, . Le dernier exemple enchaîne deux méthodes : chacune rend un nouveau tableau, sur lequel on appelle la suivante.
La suite du cours est sur Adloun
Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.
Lire la suite du coursEn accès libre, sans inscription.