Cours JavaScript et TypeScript · Module 2: Fonctions, tableaux et objets

Projet final : le système de surveillance des dinosaures

9 min de lecture
Dans cette leçon4

Bon retour au centre de commandement de Jurassic Park ! Dans ce module, tu as découvert les fonctions, les tableaux, la portée des variables, le hoisting, le mot-clé this, les objets et les prototypes. Il est maintenant temps de réunir ces connaissances dans un seul Système de Surveillance des Dinosaures intégré - le cœur opérationnel de tout le parc.

Imagine une console centrale sur laquelle les opérateurs du parc suivent en temps réel la position, l'état de santé et le comportement de chaque dinosaure. Des capteurs répartis dans tout le parc transmettent des données que notre système doit traiter, filtrer et analyser. Sans un système de surveillance efficace, le parc échapperait vite à tout contrôle - exactement comme dans le film !

Dans ce projet, tu vas créer un système complet qui utilise les fonctions fléchées pour traiter les données, les méthodes de tableau pour filtrer et transformer, les fonctions d'ordre supérieur pour une logique flexible, et les objets pour modéliser les entités du parc.

L'objectif du projet

Tu vas construire un système de surveillance qui :

  • Stocke les données sur les dinosaures dans des tableaux d'objets
  • Utilise des fonctions avec différents types de paramètres (par défaut, rest)
  • Emploie des fonctions fléchées pour un code concis
  • Filtre, transforme et réduit les données à l'aide des méthodes de tableau
  • Gère correctement la portée des variables
  • Utilise des objets dotés de méthodes pour modéliser le système

Les exigences fonctionnelles

1. La base de données des dinosaures - tableaux et objets

La première étape consiste à créer la base de données du parc. Chaque dinosaure est un objet doté de propriétés, et toute la population est stockée dans un tableau.

1// Base de données des dinosaures du parc
2const dinosaurs = [
3  {
4    id: 1,
5    name: "Rex",
6    species: "Tyrannosaurus Rex",
7    weight: 8500,
8    diet: "carnivore",
9    enclosure: "A-1",
10    isHealthy: true,
11    heartRate: 72,
12    lastFed: "2024-03-15 08:00"
13  },
14  {
15    id: 2,
16    name: "Tricia",
17    species: "Triceratops",
18    weight: 6200,
19    diet: "herbivore",
20    enclosure: "B-3",
21    isHealthy: true,
22    heartRate: 55,
23    lastFed: "2024-03-15 07:30"
24  },
25  {
26    id: 3,
27    name: "Blue",
28    species: "Velociraptor",
29    weight: 75,
30    diet: "carnivore",
31    enclosure: "C-2",
32    isHealthy: false,
33    heartRate: 110,
34    lastFed: "2024-03-14 18:00"
35  },
36  {
37    id: 4,
38    name: "Dippy",
39    species: "Diplodocus",
40    weight: 12000,
41    diet: "herbivore",
42    enclosure: "D-1",
43    isHealthy: true,
44    heartRate: 40,
45    lastFed: "2024-03-15 06:00"
46  },
47  {
48    id: 5,
49    name: "Spike",
50    species: "Stegosaurus",
51    weight: 3500,
52    diet: "herbivore",
53    enclosure: "B-2",
54    isHealthy: true,
55    heartRate: 48,
56    lastFed: "2024-03-15 07:00"
57  }
58];
59
60// Ajout d'un nouveau dinosaure à la base
61const addDinosaur = (name, species, weight, diet, enclosure) => {
62  const newId = dinosaurs.length + 1;
63  const newDino = {
64    id: newId,
65    name,
66    species,
67    weight,
68    diet,
69    enclosure,
70    isHealthy: true,
71    heartRate: 60,
72    lastFed: new Date().toISOString()
73  };
74  dinosaurs.push(newDino);
75  console.log("Enregistré :", newDino.name, "(" + newDino.species + ")");
76  return newDino;
77};
78
79addDinosaur("Echo", "Velociraptor", 68, "carnivore", "C-2");
80console.log("Nombre total de dinosaures :", dinosaurs.length);

2. Filtrage et analyse - les méthodes de tableau

Le système doit permettre de filtrer rapidement la population selon différents critères. Ici, tu vas utiliser filter, map, reduce et find.

1// Filtrage des prédateurs avec filter
2const carnivores = dinosaurs.filter(dino => dino.diet === "carnivore");
3console.log("Prédateurs :", carnivores.map(d => d.name));
4
5// Filtrage des dinosaures malades
6const unhealthyDinos = dinosaurs.filter(dino => !dino.isHealthy);
7console.log("Ont besoin de soins :", unhealthyDinos.map(d => d.name));
8
9// Mapping - création d'un rapport avec les noms et les poids
10const weightReport = dinosaurs.map(dino => {
11  return {
12    name: dino.name,
13    weight: dino.weight,
14    category: dino.weight > 5000 ? "lourd" : "léger"
15  };
16});
17console.log("Rapport des poids :");
18weightReport.forEach(entry => {
19  console.log("  " + entry.name + " : " + entry.weight + " kg (" + entry.category + ")");
20});
21
22// Réduction - calcul du poids total de tous les dinosaures
23const totalWeight = dinosaurs.reduce((sum, dino) => sum + dino.weight, 0);
24console.log("Poids total de la population :", totalWeight, "kg");
25
26// Poids moyen
27const avgWeight = totalWeight / dinosaurs.length;
28console.log("Poids moyen :", Math.round(avgWeight), "kg");
29
30// Recherche du dinosaure le plus lourd
31const heaviest = dinosaurs.reduce((max, dino) =>
32  dino.weight > max.weight ? dino : max
33);
34console.log("Le plus lourd :", heaviest.name, "-", heaviest.weight, "kg");
35
36// find - recherche d'un dinosaure précis
37const blue = dinosaurs.find(dino => dino.name === "Blue");
38console.log("Trouvé :", blue ? blue.name + " dans " + blue.enclosure : "introuvable");
39
40// some et every - vérification de conditions
41const allHealthy = dinosaurs.every(dino => dino.isHealthy);
42const anyUnhealthy = dinosaurs.some(dino => !dino.isHealthy);
43console.log("Tous en bonne santé :", allHealthy);
44console.log("Il y a des dinosaures malades :", anyUnhealthy);

3. Les fonctions de surveillance - paramètres, scope et this

Le système a besoin d'un ensemble de fonctions de surveillance avec différents types de paramètres. Fais attention à la portée des variables et à la différence entre les fonctions classiques et les fonctions fléchées dans le contexte de this.

1// Fonction avec des paramètres par défaut
2function generateAlert(dinoName, alertType = "INFO", priority = "normal") {
3  const timestamp = new Date().toLocaleTimeString();
4  console.log("[" + timestamp + "] [" + alertType + "] [" + priority + "] " + dinoName);
5}
6
7generateAlert("Rex", "WARNING", "high");
8generateAlert("Tricia"); // utilisera les valeurs par défaut
9generateAlert("Blue", "DANGER"); // priority vaudra "normal"
10
11// Fonction avec un paramètre rest - enregistrement de plusieurs événements
12const logEvents = (enclosure, ...events) => {
13  console.log("Enclos " + enclosure + " - " + events.length + " événements enregistrés :");
14  events.forEach((event, index) => {
15    console.log("  " + (index + 1) + ". " + event);
16  });
17};
18
19logEvents("A-1", "Nourrissage à 8:00", "Examen vétérinaire", "Activité physique");
20logEvents("C-2", "Tentative d'évasion !");
21
22// Objet moniteur avec des méthodes - this en contexte
23const enclosureMonitor = {
24  sector: "A",
25  alertCount: 0,
26
27  // Méthode classique - this désigne l'objet
28  checkFence: function() {
29    this.alertCount++;
30    console.log("Vérification de la clôture du secteur " + this.sector +
31                " (alerte n°" + this.alertCount + ")");
32  },
33
34  // Méthode raccourcie ES6
35  getStatus() {
36    return "Secteur " + this.sector + " - " + this.alertCount + " alertes";
37  }
38};
39
40enclosureMonitor.checkFence();
41enclosureMonitor.checkFence();
42console.log(enclosureMonitor.getStatus());
43
44// Portée des variables - de bloc vs de fonction
45function monitorHeartRates() {
46  const threshold = 100; // accessible dans toute la fonction
47
48  for (let i = 0; i < dinosaurs.length; i++) {
49    const dino = dinosaurs[i]; // accessible uniquement dans ce bloc
50    if (dino.heartRate > threshold) {
51      let pulseStatus = "ÉLEVÉ"; // accessible uniquement dans ce if
52      console.log(dino.name + " : pouls " + dino.heartRate + " - " + pulseStatus);
53    }
54  }
55
56  // console.log(pulseStatus); // ERREUR ! pulseStatus n'existe pas en dehors du bloc if
57  // console.log(dino);   // ERREUR ! dino n'existe pas en dehors de la boucle for
58  console.log("Seuil d'alerte :", threshold); // OK - threshold est dans la portée de la fonction
59}
60
61monitorHeartRates();

4. Traitement avancé - l'enchaînement des méthodes

Dans un vrai système de surveillance, nous devons souvent enchaîner plusieurs opérations. Les méthodes de tableau s'y prêtent à merveille.

1// Chaîne de méthodes - rapport de sécurité
2const securityReport = dinosaurs
3  .filter(dino => dino.diet === "carnivore") // seulement les prédateurs
4  .map(dino => ({                            // transformation des données
5    name: dino.name,
6    enclosure: dino.enclosure,
7    danger: dino.weight > 1000 ? "ÉLEVÉ" : "MOYEN"
8  }))
9  .sort((a, b) => a.name.localeCompare(b.name)); // tri
10
11console.log("=== RAPPORT DE SÉCURITÉ ===");
12securityReport.forEach(entry => {
13  console.log(entry.name + " [" + entry.enclosure + "] - danger : " + entry.danger);
14});
15
16// Regroupement des dinosaures par régime alimentaire avec reduce
17const groupedByDiet = dinosaurs.reduce((groups, dino) => {
18  const key = dino.diet;
19  if (!groups[key]) {
20    groups[key] = [];
21  }
22  groups[key].push(dino.name);
23  return groups;
24}, {});
25
26console.log("=== RÉPARTITION PAR RÉGIME ALIMENTAIRE ===");
27console.log("Herbivores :", groupedByDiet.herbivore);
28console.log("Carnivores :", groupedByDiet.carnivore);
29
30// Fonction d'ordre supérieur - création de filtres
31function createFilter(property, value) {
32  return (dino) => dino[property] === value;
33}
34
35const isCarnivore = createFilter("diet", "carnivore");
36const isInSectorB = createFilter("enclosure", "B-3");
37
38const carnivoreDinos = dinosaurs.filter(isCarnivore);
39const sectorBDinos = dinosaurs.filter(isInSectorB);
40
41console.log("Carnivores :", carnivoreDinos.map(d => d.name));
42console.log("Secteur B-3 :", sectorBDinos.map(d => d.name));
43
44// Statistiques de la population
45const stats = {
46  total: dinosaurs.length,
47  healthy: dinosaurs.filter(d => d.isHealthy).length,
48  unhealthy: dinosaurs.filter(d => !d.isHealthy).length,
49  avgHeartRate: Math.round(
50    dinosaurs.reduce((sum, d) => sum + d.heartRate, 0) / dinosaurs.length
51  ),
52  heaviest: dinosaurs.reduce((max, d) => d.weight > max.weight ? d : max).name,
53  lightest: dinosaurs.reduce((min, d) => d.weight < min.weight ? d : min).name
54};
55
56console.log("=== STATISTIQUES DE LA POPULATION ===");
57console.log("Total :", stats.total);
58console.log("En bonne santé :", stats.healthy);
59console.log("Malades :", stats.unhealthy);
60console.log("Pouls moyen :", stats.avgHeartRate, "bpm");
61console.log("Le plus lourd :", stats.heaviest);
62console.log("Le plus léger :", stats.lightest);

Conseils d'implémentation

En construisant ton système de surveillance, fais attention aux points suivants :

  1. Fonctions fléchées vs classiques - utilise les fonctions fléchées pour les callbacks (filter, map, reduce), et les fonctions classiques pour les méthodes d'objet qui ont besoin de this
  2. Paramètres par défaut - utiles quand on ne dispose pas toujours de toutes les données (par exemple la priorité d'une alerte)
  3. Paramètre rest (...args) - idéal quand le nombre d'arguments est variable (par exemple une liste d'événements)
  4. Enchaînement des méthodes - filter().map().sort() est plus lisible que des boucles imbriquées
  5. Portée des variables - let et const ont une portée de bloc, var une portée de fonction - choisis en connaissance de cause
  6. Méthodes de tableau et original - filter et map créent de nouveaux tableaux et reduce renvoie une nouvelle valeur, alors que push, splice et sort modifient l'original
  7. Les objets comme structures de données - regroupe les données liées dans des objets au lieu de les garder dans des variables séparées

Bonne chance !

Il est temps d'endosser le rôle d'opérateur en chef de Jurassic Park ! Crée ton propre Système de Surveillance dans l'éditeur ci-dessous. Combine les tableaux, les fonctions, les méthodes de tableau et les objets en un seul système qui fonctionne. N'oublie pas - chaque dinosaure du parc dépend de ton code. Comme le disait John Hammond : "Nous n'avons pas lésiné sur les dépenses" - alors toi non plus, ne lésine pas sur le code !

Code de cette leçon : index.js
1// Projet final: Système de surveillance des dinosaures
2// Combine: fonctions, tableaux, fonctions fléchées, portée, this, objets
3
4// === 1. BASE DE DONNÉES DU PARC ===
5const dinosaurs = [
6  { id: 1, name: "Rex", species: "Tyrannosaurus", weight: 8500, diet: "carnivore", enclosure: "A-1", isHealthy: true, heartRate: 72 },
7  { id: 2, name: "Tricia", species: "Triceratops", weight: 6200, diet: "herbivore", enclosure: "B-3", isHealthy: true, heartRate: 55 },
8  { id: 3, name: "Blue", species: "Velociraptor", weight: 75, diet: "carnivore", enclosure: "C-2", isHealthy: false, heartRate: 110 },
9];
10
11// === 2. SYSTÈME DE SURVEILLANCE ===
12// TODO: Crée un objet monitoringSystem avec des méthodes qui utilisent this
13const monitoringSystem = {
14  parkName: "Jurassic Park",
15  alerts: [],
16
17  // TODO: Méthode filtrant les dinosaures par régime (utilise une fonction fléchée)
18  filterByDiet: (dinos, diet) => {
19    // TODO: Utilise filter()
20  },
21
22  // TODO: Méthode générant un rapport de santé (utilise map)
23  getHealthReport(dinos) {
24    // TODO: Utilise map() pour créer un rapport pour chaque dinosaure
25    // Retourne un tableau d'objets: { name, status, heartRate }
26  },
27
28  // TODO: Méthode calculant le poids moyen (utilise reduce)
29  calculateAverageWeight(dinos) {
30    // TODO: Utilise reduce() pour calculer la moyenne
31  },
32
33  // TODO: Méthode ajoutant une alerte
34  addAlert(message, severity) {
35    // TODO: Ajoute une alerte avec un horodatage (timestamp) à this.alerts
36  },
37};
38
39// === 3. FONCTIONS D'ORDRE SUPÉRIEUR ===
40// TODO: Crée une fonction createFilter qui retourne une fonction de filtrage
41function createFilter(property, value) {
42  // TODO: Retourne une fonction fléchée qui filtre selon la propriété donnée
43}
44
45// === 4. RAPPORT FINAL ===
46// TODO: Génère et affiche un rapport complet de surveillance
47// - Liste des dinosaures par régime
48// - Rapport de santé
49// - Poids moyen
50// - Alertes actives
51
52console.log("Système de surveillance démarré !");

Tu as repéré une erreur dans cette leçon ?

Articles utiles