Cours JavaScript et TypeScript · Module 2: Fonctions, tableaux et objets
Créer des objets (littéraux, constructeurs)
Dans cette leçon8
À Jurassic Park, nous utilisons les objets JavaScript pour représenter de nombreux éléments de notre écosystème - des dinosaures et de leurs comportements, en passant par les zones du parc, jusqu'aux données du personnel et aux procédures de sécurité. Les objets sont un type de données fondamental en JavaScript, qui permet de créer des structures de données complexes dotées de propriétés et de méthodes.
Les littéraux d'objet
La façon la plus simple de créer des objets en JavaScript consiste à utiliser un littéral d'objet - la notation avec des accolades {}.
1// Un objet dinosaure simple, créé à l'aide d'un littéral d'objet
2const velociraptor = {
3 name: "Blue",
4 species: "Velociraptor",
5 age: 4,
6 length: 2.1, // mètres
7 weight: 80, // kilogrammes
8 maxSpeed: 64, // km/h
9 diet: "carnivore",
10 location: "Secteur B",
11 dangerous: true
12};
13
14console.log(velociraptor.name); // "Blue"
15console.log(velociraptor.species); // "Velociraptor"
16console.log(velociraptor.maxSpeed); // 64Accéder aux propriétés
Nous pouvons accéder aux propriétés d'un objet de deux façons :
1// Notation pointée
2console.log(velociraptor.diet); // "carnivore"
3
4// Notation entre crochets (utile quand le nom de la propriété est stocké dans une variable)
5const propertyName = "location";
6console.log(velociraptor[propertyName]); // "Secteur B"
7
8// La notation entre crochets est aussi utile quand le nom de la propriété contient des caractères spéciaux ou des espaces
9const dinoDetails = {
10 "full name": "Velociraptor antirrhopus",
11 "security-level": "Alpha"
12};
13
14console.log(dinoDetails["full name"]); // "Velociraptor antirrhopus"
15console.log(dinoDetails["security-level"]); // "Alpha"Les méthodes d'objet
Les objets peuvent aussi contenir des fonctions, que nous appelons des méthodes :
1const velociraptor = {
2 name: "Blue",
3 species: "Velociraptor",
4 age: 4,
5 hunger: 50, // pourcentage (0-100)
6 health: 100, // pourcentage (0-100)
7
8 // Méthode pour nourrir le dinosaure
9 feed: function() {
10 if (this.hunger <= 0) {
11 return "Blue n'a pas faim.";
12 }
13
14 this.hunger -= 30;
15 if (this.hunger < 0) this.hunger = 0;
16
17 return "Blue a été nourrie. Niveau de faim : " + this.hunger + "%";
18 },
19
20 // Syntaxe de méthode raccourcie (introduite avec ES6)
21 makeSound() {
22 return "Blue pousse un cri aigu et perçant !";
23 },
24
25 // Méthode qui vérifie l'état de santé
26 checkStatus() {
27 return `Dinosaure : ${this.name} (Espèce : ${this.species})
28État de santé : ${this.health}%
29Niveau de faim : ${this.hunger}%
30État général : ${this.health > 80 ? "Excellent" : this.health > 50 ? "Bon" : "Nécessite des soins vétérinaires"}`;
31 }
32};
33
34console.log(velociraptor.makeSound()); // "Blue pousse un cri aigu et perçant !"
35console.log(velociraptor.feed()); // "Blue a été nourrie. Niveau de faim : 20%"
36console.log(velociraptor.checkStatus());Dans les méthodes, le mot-clé this fait référence à l'objet sur lequel la méthode est appelée.
Ajouter et supprimer des propriétés dynamiquement
Nous pouvons ajouter et supprimer dynamiquement des propriétés des objets JavaScript :
1const triceratops = {
2 name: "Trixie",
3 species: "Triceratops",
4 age: 6
5};
6
7// Ajout de nouvelles propriétés
8triceratops.health = 95;
9triceratops["location"] = "Secteur C";
10
11// Ajout d'une méthode
12triceratops.updateHealth = function(amount) {
13 this.health += amount;
14 if (this.health > 100) this.health = 100;
15 if (this.health < 0) this.health = 0;
16 return `Santé de ${this.name} mise à jour à ${this.health}%`;
17};
18
19console.log(triceratops.updateHealth(-15)); // "Santé de Trixie mise à jour à 80%"
20
21// Suppression d'une propriété
22delete triceratops.age;
23console.log(triceratops.age); // undefinedLes constructeurs et l'opérateur new
Quand nous devons créer de nombreux objets similaires, une approche plus efficace consiste à utiliser une fonction constructeur et l'opérateur new.
1// Fonction constructeur pour les dinosaures
2function Dinosaur(name, species, age, diet) {
3 this.name = name;
4 this.species = species;
5 this.age = age;
6 this.diet = diet;
7 this.health = 100;
8 this.hunger = 50;
9
10 // Méthode commune à tous les dinosaures
11 this.feed = function() {
12 this.hunger -= 30;
13 if (this.hunger < 0) this.hunger = 0;
14 return `${this.name} a été nourri(e). Niveau de faim : ${this.hunger}%`;
15 };
16}
17
18// Création de nouvelles instances de dinosaures
19const blue = new Dinosaur("Blue", "Velociraptor", 4, "carnivore");
20const trixie = new Dinosaur("Trixie", "Triceratops", 6, "herbivore");
21const rex = new Dinosaur("Rex", "Tyrannosaurus", 8, "carnivore");
22
23console.log(blue.species); // "Velociraptor"
24console.log(trixie.diet); // "herbivore"
25console.log(rex.feed()); // "Rex a été nourri(e). Niveau de faim : 20%"La fonction constructeur crée un "modèle" pour les objets, et l'opérateur new crée une nouvelle instance d'objet d'après ce modèle.
Les avantages des constructeurs :
- Cohérence - tous les objets ont le même ensemble de propriétés et de méthodes
- Évolutivité - il est plus facile de créer de nombreux objets similaires
- Lisibilité - le code devient plus prévisible et plus facile à maintenir
Vérifier le type d'un objet - l'opérateur instanceof
Nous pouvons vérifier si un objet a été créé à l'aide d'un constructeur précis :
1console.log(blue instanceof Dinosaur); // true
2console.log(velociraptor instanceof Dinosaur); // false (il a été créé sous forme de littéral)Les classes (ES6+)
Les versions plus récentes de JavaScript (ES6+) ont introduit les classes, qui offrent une syntaxe plus conviviale pour la programmation orientée objet. Sous le capot, ce sont toujours des fonctions constructeurs, mais avec une syntaxe plus lisible.
1class Dinosaur {
2 constructor(name, species, age, diet) {
3 this.name = name;
4 this.species = species;
5 this.age = age;
6 this.diet = diet;
7 this.health = 100;
8 this.hunger = 50;
9 this.isAsleep = false;
10 }
11
12 // Les méthodes sont automatiquement ajoutées au prototype
13 feed() {
14 if (this.isAsleep) {
15 return `${this.name} dort. Mieux vaut ne pas le/la réveiller pendant le nourrissage.`;
16 }
17
18 this.hunger -= 30;
19 if (this.hunger < 0) this.hunger = 0;
20 return `${this.name} a été nourri(e). Niveau de faim : ${this.hunger}%`;
21 }
22
23 sleep() {
24 this.isAsleep = true;
25 return `${this.name} s'endort.`;
26 }
27
28 wakeUp() {
29 this.isAsleep = false;
30 return `${this.name} se réveille.`;
31 }
32
33 getStatus() {
34 return `
35Dinosaure : ${this.name} (Espèce : ${this.species})
36Âge : ${this.age} ans
37Régime : ${this.diet === "carnivore" ? "Carnivore" : "Herbivore"}
38État de santé : ${this.health}%
39Niveau de faim : ${this.hunger}%
40État : ${this.isAsleep ? "Endormi" : "Actif"}`;
41 }
42}
43
44// Création d'une instance de la classe
45const blue = new Dinosaur("Blue", "Velociraptor", 4, "carnivore");
46console.log(blue.getStatus());
47
48console.log(blue.sleep()); // "Blue s'endort."
49console.log(blue.feed()); // "Blue dort. Mieux vaut ne pas le/la réveiller pendant le nourrissage."
50console.log(blue.wakeUp()); // "Blue se réveille."
51console.log(blue.feed()); // "Blue a été nourri(e). Niveau de faim : 20%"L'héritage avec les classes
Les classes permettent d'implémenter facilement l'héritage :
1// Classe de base
2class Animal {
3 constructor(name, species) {
4 this.name = name;
5 this.species = species;
6 this.alive = true;
7 }
8
9 makeSound() {
10 return "L'animal émet un son";
11 }
12}
13
14// Classe dérivée qui hérite de Animal
15class Dinosaur extends Animal {
16 constructor(name, species, diet) {
17 // On appelle le constructeur de la classe de base
18 super(name, species);
19 this.diet = diet;
20 this.health = 100;
21 }
22
23 // On redéfinit la méthode de la classe de base
24 makeSound() {
25 if (this.diet === "carnivore") {
26 return "ROAR !!! Un rugissement terrifiant !";
27 } else {
28 return "Un grondement doux et grave.";
29 }
30 }
31
32 // On ajoute de nouvelles méthodes
33 eat(food) {
34 if (this.diet === "carnivore" && food.type === "meat") {
35 return `${this.name} dévore ${food.name} avec appétit !`;
36 } else if (this.diet === "herbivore" && food.type === "plant") {
37 return `${this.name} broute ${food.name} avec satisfaction.`;
38 } else {
39 return `${this.name} n'a aucune envie de manger ${food.name}.`;
40 }
41 }
42}
43
44// Objets qui représentent la nourriture
45const meat = { name: "la viande", type: "meat" };
46const plants = { name: "les plantes", type: "plant" };
47
48// On crée des instances de dinosaures
49const rex = new Dinosaur("Rex", "Tyrannosaurus", "carnivore");
50const spike = new Dinosaur("Spike", "Stegosaurus", "herbivore");
51
52console.log(rex.makeSound()); // "ROAR !!! Un rugissement terrifiant !"
53console.log(spike.makeSound()); // "Un grondement doux et grave."
54
55console.log(rex.eat(meat)); // "Rex dévore la viande avec appétit !"
56console.log(rex.eat(plants)); // "Rex n'a aucune envie de manger les plantes."
57console.log(spike.eat(plants)); // "Spike broute les plantes avec satisfaction."Les méthodes statiques
Les méthodes statiques sont appelées sur la classe elle-même, et non sur ses instances :
1class DinosaurDatabase {
2 static dinoCount = 0;
3
4 constructor(name, species) {
5 this.name = name;
6 this.species = species;
7 DinosaurDatabase.dinoCount++;
8 }
9
10 // Méthode d'instance - nécessite de créer un objet
11 getInfo() {
12 return `${this.name} (${this.species})`;
13 }
14
15 // Méthode statique - appelée sur la classe, pas sur une instance
16 static getTotalDinosaurCount() {
17 return `Nombre total de dinosaures dans la base : ${DinosaurDatabase.dinoCount}`;
18 }
19
20 static compareAge(dino1, dino2) {
21 if (!dino1.age || !dino2.age) return "Aucune donnée sur l'âge.";
22
23 if (dino1.age > dino2.age) {
24 return `${dino1.name} est plus âgé que ${dino2.name}.`;
25 } else if (dino1.age < dino2.age) {
26 return `${dino1.name} est plus jeune que ${dino2.name}.`;
27 } else {
28 return `${dino1.name} et ${dino2.name} ont le même âge.`;
29 }
30 }
31}
32
33const dino1 = new DinosaurDatabase("Rex", "Tyrannosaurus");
34dino1.age = 8;
35
36const dino2 = new DinosaurDatabase("Blue", "Velociraptor");
37dino2.age = 4;
38
39const dino3 = new DinosaurDatabase("Trixie", "Triceratops");
40dino3.age = 6;
41
42console.log(DinosaurDatabase.getTotalDinosaurCount()); // "Nombre total de dinosaures dans la base : 3"
43console.log(DinosaurDatabase.compareAge(dino1, dino2)); // "Rex est plus âgé que Blue."
44console.log(DinosaurDatabase.compareAge(dino2, dino3)); // "Blue est plus jeune que Trixie."Object.create()
La méthode Object.create() permet de créer de nouveaux objets avec un prototype déterminé :
1// Objet prototype pour tous les dinosaures
2const dinoPrototype = {
3 makeSound() {
4 return "Rugissement !";
5 },
6 eat() {
7 return `${this.name} mange.`;
8 }
9};
10
11// Création d'un objet avec le prototype dinoPrototype
12const rex = Object.create(dinoPrototype);
13rex.name = "Rex";
14rex.species = "Tyrannosaurus";
15
16console.log(rex.name); // "Rex"
17console.log(rex.makeSound()); // "Rugissement !"
18console.log(rex.eat()); // "Rex mange."Factory Functions (fonctions fabriques)
Les fonctions fabriques sont des fonctions qui créent et renvoient des objets sans utiliser new :
1// Fonction fabrique pour créer des objets dinosaures
2function createDinosaur(name, species, diet) {
3 return {
4 name, // Syntaxe raccourcie pour name: name en ES6+
5 species,
6 diet,
7 health: 100,
8 hunger: 50,
9
10 feed() {
11 this.hunger -= 30;
12 if (this.hunger < 0) this.hunger = 0;
13 return `${this.name} a été nourri(e). Niveau de faim : ${this.hunger}%`;
14 },
15
16 getStatus() {
17 return `${this.name} (${this.species}) - Santé : ${this.health}%, Faim : ${this.hunger}%`;
18 }
19 };
20}
21
22const blue = createDinosaur("Blue", "Velociraptor", "carnivore");
23const trixie = createDinosaur("Trixie", "Triceratops", "herbivore");
24
25console.log(blue.getStatus()); // "Blue (Velociraptor) - Santé : 100%, Faim : 50%"
26console.log(blue.feed()); // "Blue a été nourri(e). Niveau de faim : 20%"Utilisation pratique des objets à Jurassic Park
Le système de gestion des dinosaures
1class DinosaurManager {
2 constructor() {
3 this.dinosaurs = [];
4 this.enclosures = [];
5 }
6
7 addDinosaur(dino) {
8 this.dinosaurs.push(dino);
9 console.log(`Nouveau dinosaure ajouté : ${dino.name} (${dino.species})`);
10 }
11
12 addEnclosure(enclosure) {
13 this.enclosures.push(enclosure);
14 console.log(`Nouvel enclos ajouté : ${enclosure.name} (Capacité : ${enclosure.capacity})`);
15 }
16
17 assignDinosaurToEnclosure(dinoName, enclosureName) {
18 const dino = this.dinosaurs.find(d => d.name === dinoName);
19 const enclosure = this.enclosures.find(e => e.name === enclosureName);
20
21 if (!dino) {
22 return `Erreur : dinosaure nommé ${dinoName} introuvable.`;
23 }
24
25 if (!enclosure) {
26 return `Erreur : enclos nommé ${enclosureName} introuvable.`;
27 }
28
29 if (enclosure.dinosaurs.length >= enclosure.capacity) {
30 return `Erreur : l'enclos ${enclosureName} a atteint sa capacité maximale.`;
31 }
32
33 // On vérifie que les prédateurs ne sont pas mélangés aux herbivores
34 if (enclosure.dinosaurs.length > 0) {
35 const existingDiet = enclosure.dinosaurs[0].diet;
36 if (dino.diet === "carnivore" && existingDiet === "herbivore") {
37 return "Erreur : impossible de placer des prédateurs avec des herbivores !";
38 }
39 if (dino.diet === "herbivore" && existingDiet === "carnivore") {
40 return "Erreur : impossible de placer des herbivores avec des prédateurs !";
41 }
42 }
43
44 // On retire le dinosaure de son enclos précédent, s'il y était affecté
45 this.enclosures.forEach(e => {
46 const index = e.dinosaurs.findIndex(d => d.name === dinoName);
47 if (index !== -1) {
48 e.dinosaurs.splice(index, 1);
49 }
50 });
51
52 // On affecte le dinosaure au nouvel enclos
53 enclosure.dinosaurs.push(dino);
54 dino.enclosure = enclosureName;
55
56 return `${dinoName} a été affecté(e) à l'enclos ${enclosureName}.`;
57 }
58
59 getEnclosureReport(enclosureName) {
60 const enclosure = this.enclosures.find(e => e.name === enclosureName);
61
62 if (!enclosure) {
63 return `Erreur : enclos nommé ${enclosureName} introuvable.`;
64 }
65
66 let report = `=== RAPPORT DE L'ENCLOS : ${enclosure.name} ===
67Capacité : ${enclosure.dinosaurs.length}/${enclosure.capacity}
68Statut : ${enclosure.status}
69Dinosaures :\n`;
70
71 if (enclosure.dinosaurs.length === 0) {
72 report += "Aucun dinosaure dans cet enclos.";
73 } else {
74 enclosure.dinosaurs.forEach(dino => {
75 report += `- ${dino.name} (${dino.species}) : Santé : ${dino.health}%, Faim : ${dino.hunger}%\n`;
76 });
77 }
78
79 return report;
80 }
81}
82
83// Classe pour les dinosaures
84class Dinosaur {
85 constructor(name, species, diet) {
86 this.name = name;
87 this.species = species;
88 this.diet = diet;
89 this.health = 100;
90 this.hunger = 50;
91 this.enclosure = null; // Nom de l'enclos auquel le dinosaure est affecté
92 }
93}
94
95// Classe pour les enclos
96class Enclosure {
97 constructor(name, capacity, security) {
98 this.name = name;
99 this.capacity = capacity;
100 this.security = security; // niveau de sécurité
101 this.status = "Operational";
102 this.dinosaurs = []; // Liste des dinosaures présents dans l'enclos
103 }
104}
105
106// Utilisation du système de gestion
107const parkManager = new DinosaurManager();
108
109// Création des enclos
110const carnivoreEnclosure = new Enclosure("Paddock A", 3, "Maximum");
111const herbivoreEnclosure = new Enclosure("Paddock B", 5, "Standard");
112
113parkManager.addEnclosure(carnivoreEnclosure);
114parkManager.addEnclosure(herbivoreEnclosure);
115
116// Création des dinosaures
117const rex = new Dinosaur("Rex", "Tyrannosaurus", "carnivore");
118const blue = new Dinosaur("Blue", "Velociraptor", "carnivore");
119const trixie = new Dinosaur("Trixie", "Triceratops", "herbivore");
120const spike = new Dinosaur("Spike", "Stegosaurus", "herbivore");
121
122parkManager.addDinosaur(rex);
123parkManager.addDinosaur(blue);
124parkManager.addDinosaur(trixie);
125parkManager.addDinosaur(spike);
126
127// Affectation des dinosaures aux enclos
128console.log(parkManager.assignDinosaurToEnclosure("Rex", "Paddock A"));
129console.log(parkManager.assignDinosaurToEnclosure("Blue", "Paddock A"));
130console.log(parkManager.assignDinosaurToEnclosure("Trixie", "Paddock B"));
131console.log(parkManager.assignDinosaurToEnclosure("Spike", "Paddock B"));
132
133// Tentative d'affecter un herbivore à l'enclos des prédateurs
134console.log(parkManager.assignDinosaurToEnclosure("Trixie", "Paddock A"));
135
136// Affichage des rapports
137console.log(parkManager.getEnclosureReport("Paddock A"));
138console.log(parkManager.getEnclosureReport("Paddock B"));Résumé
Les objets sont un élément fondamental du langage JavaScript et nous permettent de modéliser des structures de données et des comportements complexes. À Jurassic Park, nous les utilisons pour tout représenter - des dinosaures jusqu'au système de gestion du parc tout entier.
Nous disposons de plusieurs façons de créer des objets :
- Les littéraux d'objet - la façon la plus simple, idéale pour des objets isolés et uniques
- Les fonctions constructeurs - quand nous devons créer de nombreux objets similaires
- Les classes (ES6+) - une syntaxe moderne et lisible pour créer des modèles d'objets avec héritage
- Object.create() - la création d'objets avec un prototype déterminé
- Les fonctions fabriques - des fonctions qui renvoient de nouveaux objets, une alternative aux constructeurs
Le choix d'une technique précise dépend de la situation et des besoins du projet. Dans les applications complexes, comme notre système de gestion de Jurassic Park, nous utilisons le plus souvent une combinaison de ces techniques.
Code de cette leçon : index.js
1// Objets - création - Parc Jurassique
2console.log("Laboratoire des Objets JavaScript");
3console.log("Création et construction d'objets\n");
4
5// ===========================================
6// 1. LITTÉRAUX D'OBJETS (la façon la plus simple)
7// ===========================================
8console.log("=== 1. Littéraux d'objets ===");
9
10// Objet de base
11const dinosaur1 = {
12 name: "T-Rex",
13 species: "Tyrannosaurus Rex",
14 age: 8,
15 weight: 8000,
16 carnivore: true
17};
18
19console.log("Dinosaure 1:");
20console.log(` Nom: ${dinosaur1.name}`);
21console.log(` Espèce: ${dinosaur1.species}`);
22console.log(` Âge: ${dinosaur1.age} ans`);
23
24// Objet avec des méthodes
25const dinosaur2 = {
26 name: "Blue",
27 species: "Velociraptor",
28 speed: 40,
29
30 // Méthode traditionnelle
31 roar: function() {
32 return `${this.name} rugit: SHREEK!`;
33 },
34
35 // Méthode abrégée (ES6)
36 run() {
37 return `${this.name} court à ${this.speed} km/h`;
38 }
39};
40
41console.log("\nDinosaure 2:");
42console.log(` ${dinosaur2.roar()}`);
43console.log(` ${dinosaur2.run()}`);
44
45// ===========================================
46// 2. FONCTIONS CONSTRUCTEURS
47// ===========================================
48console.log("\n=== 2. Fonctions constructeurs ===");
49
50function Dinosaur(name, species, age, weight, carnivore) {
51 this.name = name;
52 this.species = species;
53 this.age = age;
54 this.weight = weight;
55 this.carnivore = carnivore;
56
57 this.getInfo = function() {
58 return `${this.name} (${this.species}) - ${this.age} ans, ${this.weight}kg`;
59 };
60
61 this.roar = function() {
62 return `${this.name} rugit: ROAARRR!`;
63 };
64}
65
66const trex = new Dinosaur("Rexy", "T-Rex", 8, 8000, true);
67const trike = new Dinosaur("Trike", "Triceratops", 7, 9000, false);
68
69console.log("\nCréé via un constructeur:");
70console.log(` ${trex.getInfo()}`);
71console.log(` ${trex.roar()}`);
72console.log(` ${trike.getInfo()}`);
73
74// ===========================================
75// 3. Object.create()
76// ===========================================
77console.log("\n=== 3. Object.create() ===");
78
79const dinoPrototype = {
80 getInfo() {
81 return `${this.name} (${this.species})`;
82 },
83
84 roar() {
85 return `${this.name}: ROAARRR!`;
86 }
87};
88
89const velociraptor = Object.create(dinoPrototype);
90velociraptor.name = "Charlie";
91velociraptor.species = "Velociraptor";
92velociraptor.age = 5;
93
94console.log("\nCréé via Object.create():");
95console.log(` ${velociraptor.getInfo()}`);
96console.log(` ${velociraptor.roar()}`);
97
98// ===========================================
99// 4. CLASSES ES6
100// ===========================================
101console.log("\n=== 4. Classes ES6 ===");
102
103class DinosaurClass {
104 constructor(name, species, age, weight, carnivore) {
105 this.name = name;
106 this.species = species;
107 this.age = age;
108 this.weight = weight;
109 this.carnivore = carnivore;
110 }
111
112 getInfo() {
113 return `${this.name} (${this.species}) - ${this.age} ans, ${this.weight}kg`;
114 }
115
116 roar() {
117 return `${this.name} rugit: ROAARRR!`;
118 }
119
120 isHeavy() {
121 return this.weight > 1000;
122 }
123}
124
125const stego = new DinosaurClass("Stego", "Stegosaurus", 6, 5000, false);
126const brachio = new DinosaurClass("Brachio", "Brachiosaurus", 10, 50000, false);
127
128console.log("\nCréé via une classe:");
129console.log(` ${stego.getInfo()}`);
130console.log(` Est-il lourd ? ${stego.isHeavy()}`);
131console.log(` ${brachio.getInfo()}`);
132console.log(` Est-il lourd ? ${brachio.isHeavy()}`);
133
134// ===========================================
135// 5. FONCTIONS FABRIQUES (FACTORY FUNCTIONS)
136// ===========================================
137console.log("\n=== 5. Fonctions fabriques (factory) ===");
138
139function createDinosaur(name, species, options = {}) {
140 return {
141 name,
142 species,
143 age: options.age || 5,
144 weight: options.weight || 100,
145 carnivore: options.carnivore || false,
146 sector: options.sector || "A",
147
148 getInfo() {
149 return `${this.name} (${this.species}) - Secteur ${this.sector}`;
150 },
151
152 feed() {
153 console.log(`Nourrissage de ${this.name}`);
154 }
155 };
156}
157
158const dilo = createDinosaur("Dilo", "Dilophosaurus", {
159 age: 4,
160 weight: 400,
161 carnivore: true,
162 sector: "E"
163});
164
165console.log("\nCréé via une fonction fabrique:");
166console.log(` ${dilo.getInfo()}`);
167dilo.feed();
168
169// ===========================================
170// 6. OBJETS IMBRIQUÉS
171// ===========================================
172console.log("\n=== 6. Objets imbriqués ===");
173
174const park = {
175 name: "Jurassic Park",
176 location: "Isla Nublar",
177
178 sectors: {
179 A: { name: "Zone des carnivores", capacity: 5, current: 2 },
180 B: { name: "Enclos des raptors", capacity: 10, current: 3 },
181 C: { name: "Vallée des herbivores", capacity: 20, current: 8 }
182 },
183
184 stats: {
185 totalDinosaurs: 13,
186 totalVisitors: 1500,
187 securityLevel: "ÉLEVÉ"
188 },
189
190 getReport() {
191 console.log(`\nRapport du parc ${this.name}:`);
192 console.log(` Localisation: ${this.location}`);
193 console.log(` Dinosaures: ${this.stats.totalDinosaurs}`);
194 console.log(` Visiteurs: ${this.stats.totalVisitors}`);
195 console.log(` Sécurité: ${this.stats.securityLevel}`);
196 }
197};
198
199park.getReport();
200
201console.log("\nSecteurs:");
202Object.entries(park.sectors).forEach(([key, sector]) => {
203 console.log(` ${key}: ${sector.name} - ${sector.current}/${sector.capacity}`);
204});
205
206// ===========================================
207// 7. GETTERS ET SETTERS
208// ===========================================
209console.log("\n=== 7. Getters et setters ===");
210
211class ManagedDinosaur {
212 constructor(name, species, health) {
213 this.name = name;
214 this.species = species;
215 this._health = health; // Propriété privée (convention)
216 }
217
218 // Getter
219 get health() {
220 return this._health;
221 }
222
223 // Setter avec validation
224 set health(value) {
225 if (value < 0) value = 0;
226 if (value > 100) value = 100;
227 this._health = value;
228 console.log(` Santé de ${this.name} changée à ${this._health}%`);
229 }
230
231 get status() {
232 if (this._health >= 80) return "En bonne santé";
233 if (this._health >= 50) return "Moyen";
234 return "Critique";
235 }
236}
237
238const managedDino = new ManagedDinosaur("Rex", "T-Rex", 75);
239console.log(`\n${managedDino.name}:`);
240console.log(` Santé: ${managedDino.health}%`);
241console.log(` Statut: ${managedDino.status}`);
242
243managedDino.health = 95;
244console.log(` Nouveau statut: ${managedDino.status}`);
245
246managedDino.health = 150; // Sera limitée à 100
247console.log(` Statut après dépassement: ${managedDino.status}`);
248
249// ===========================================
250// 8. MÉTHODES ET PROPRIÉTÉS STATIQUES
251// ===========================================
252console.log("\n=== 8. Méthodes et propriétés statiques ===");
253
254class DinoSpecies {
255 static species = [
256 "Tyrannosaurus Rex",
257 "Velociraptor",
258 "Triceratops",
259 "Stegosaurus",
260 "Brachiosaurus"
261 ];
262
263 static isCarnivore(species) {
264 const carnivores = ["Tyrannosaurus Rex", "Velociraptor", "Spinosaurus"];
265 return carnivores.includes(species);
266 }
267
268 static getInfo(species) {
269 const info = {
270 "Tyrannosaurus Rex": { weight: 8000, period: "Crétacé" },
271 "Velociraptor": { weight: 80, period: "Crétacé" },
272 "Triceratops": { weight: 9000, period: "Crétacé" }
273 };
274 return info[species] || { weight: "?", period: "?" };
275 }
276
277 static listAll() {
278 console.log("\nToutes les espèces:");
279 this.species.forEach((s, i) => {
280 const carnivore = this.isCarnivore(s) ? "carnivore" : "herbivore";
281 console.log(` ${i + 1}. ${carnivore} ${s}`);
282 });
283 }
284}
285
286DinoSpecies.listAll();
287
288console.log("\nVérification des espèces:");
289console.log(` T-Rex carnivore ? ${DinoSpecies.isCarnivore("Tyrannosaurus Rex")}`);
290console.log(` Triceratops carnivore ? ${DinoSpecies.isCarnivore("Triceratops")}`);
291
292const trexInfo = DinoSpecies.getInfo("Tyrannosaurus Rex");
293console.log(`\nInfo sur le T-Rex: poids ${trexInfo.weight}kg, période ${trexInfo.period}`);
294
295// ===========================================
296// 9. HÉRITAGE
297// ===========================================
298console.log("\n=== 9. Héritage ===");
299
300class Animal {
301 constructor(name, age) {
302 this.name = name;
303 this.age = age;
304 }
305
306 breathe() {
307 return `${this.name} respire`;
308 }
309
310 getAge() {
311 return `${this.name} a ${this.age} ans`;
312 }
313}
314
315class Carnivore extends Animal {
316 constructor(name, age, huntingSkill) {
317 super(name, age);
318 this.huntingSkill = huntingSkill;
319 this.type = "Carnivore";
320 }
321
322 hunt() {
323 return `${this.name} chasse (compétence: ${this.huntingSkill}/10)`;
324 }
325
326 roar() {
327 return `${this.name} rugit: ROAARRR!`;
328 }
329}
330
331class Herbivore extends Animal {
332 constructor(name, age, plantPreference) {
333 super(name, age);
334 this.plantPreference = plantPreference;
335 this.type = "Herbivore";
336 }
337
338 eat() {
339 return `${this.name} mange ${this.plantPreference}`;
340 }
341
342 graze() {
343 return `${this.name} broute tranquillement`;
344 }
345}
346
347const rex = new Carnivore("Rexy", 8, 10);
348const trico = new Herbivore("Trico", 7, "fougères");
349
350console.log("\nCarnivore:");
351console.log(` ${rex.getAge()}`);
352console.log(` ${rex.breathe()}`);
353console.log(` ${rex.hunt()}`);
354console.log(` ${rex.roar()}`);
355
356console.log("\nHerbivore:");
357console.log(` ${trico.getAge()}`);
358console.log(` ${trico.breathe()}`);
359console.log(` ${trico.eat()}`);
360console.log(` ${trico.graze()}`);
361
362// ===========================================
363// 10. EXEMPLE COMPLET
364// ===========================================
365console.log("\n=== 10. Système de gestion - exemple complet ===");
366
367class ParkManagementSystem {
368 constructor(parkName) {
369 this.parkName = parkName;
370 this.dinosaurs = new Map();
371 this.nextId = 1;
372 }
373
374 addDinosaur(name, species, options = {}) {
375 const dino = {
376 id: this.nextId++,
377 name,
378 species,
379 age: options.age || 5,
380 weight: options.weight || 1000,
381 health: options.health || 100,
382 sector: options.sector || "A",
383 carnivore: options.carnivore || false,
384 fed: false,
385 lastCheckup: new Date()
386 };
387
388 this.dinosaurs.set(dino.id, dino);
389 console.log(`Ajouté: ${name} (#${dino.id})`);
390 return dino.id;
391 }
392
393 getDinosaur(id) {
394 return this.dinosaurs.get(id);
395 }
396
397 removeDinosaur(id) {
398 const dino = this.dinosaurs.get(id);
399 if (dino) {
400 this.dinosaurs.delete(id);
401 console.log(`Supprimé: ${dino.name} (#${id})`);
402 return true;
403 }
404 return false;
405 }
406
407 feedDinosaur(id) {
408 const dino = this.dinosaurs.get(id);
409 if (dino) {
410 dino.fed = true;
411 console.log(`Nourri: ${dino.name}`);
412 }
413 }
414
415 updateHealth(id, newHealth) {
416 const dino = this.dinosaurs.get(id);
417 if (dino) {
418 dino.health = Math.max(0, Math.min(100, newHealth));
419 console.log(`Santé mise à jour pour ${dino.name}: ${dino.health}%`);
420 }
421 }
422
423 getStats() {
424 const dinos = Array.from(this.dinosaurs.values());
425
426 return {
427 total: dinos.length,
428 carnivores: dinos.filter(d => d.carnivore).length,
429 avgHealth: (dinos.reduce((sum, d) => sum + d.health, 0) / dinos.length).toFixed(1),
430 fed: dinos.filter(d => d.fed).length,
431 bySector: dinos.reduce((acc, d) => {
432 acc[d.sector] = (acc[d.sector] || 0) + 1;
433 return acc;
434 }, {})
435 };
436 }
437
438 displayReport() {
439 console.log(`\n============================================================`);
440 console.log(`RAPPORT DU PARC: ${this.parkName}`);
441 console.log("=".repeat(60));
442
443 const stats = this.getStats();
444 console.log("\nStatistiques:");
445 console.log(` Total des dinosaures: ${stats.total}`);
446 console.log(` Carnivores: ${stats.carnivores}`);
447 console.log(` Santé moyenne: ${stats.avgHealth}%`);
448 console.log(` Nourris: ${stats.fed}/${stats.total}`);
449
450 console.log("\nRépartition par secteurs:");
451 Object.entries(stats.bySector).sort().forEach(([sector, count]) => {
452 console.log(` Secteur ${sector}: ${count}`);
453 });
454
455 console.log("\nListe des dinosaures:");
456 Array.from(this.dinosaurs.values())
457 .sort((a, b) => a.id - b.id)
458 .forEach(dino => {
459 const icon = dino.carnivore ? "carnivore" : "herbivore";
460 const fedStatus = dino.fed ? "√" : "×";
461 console.log(` #${dino.id} ${icon} ${dino.name} (${dino.species})`);
462 console.log(` Secteur ${dino.sector} | Santé: ${dino.health}% | Nourri: ${fedStatus}`);
463 });
464 }
465}
466
467// Démonstration du système
468console.log();
469const parkSystem = new ParkManagementSystem("Isla Nublar");
470
471const id1 = parkSystem.addDinosaur("Rexy", "T-Rex", { age: 8, weight: 8000, sector: "A", carnivore: true });
472const id2 = parkSystem.addDinosaur("Blue", "Velociraptor", { age: 5, weight: 80, sector: "B", carnivore: true, health: 100 });
473const id3 = parkSystem.addDinosaur("Charlie", "Velociraptor", { age: 5, weight: 80, sector: "B", carnivore: true, health: 85 });
474const id4 = parkSystem.addDinosaur("Trike", "Triceratops", { age: 7, weight: 9000, sector: "C", health: 70 });
475const id5 = parkSystem.addDinosaur("Stego", "Stegosaurus", { age: 6, weight: 5000, sector: "C" });
476
477console.log();
478parkSystem.feedDinosaur(id1);
479parkSystem.feedDinosaur(id2);
480parkSystem.updateHealth(id4, 85);
481
482parkSystem.displayReport();
483
484console.log("\nFélicitations ! Tu maîtrises maintenant la création d'objets !");Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Quelles sont les deux façons d'accéder aux propriétés d'un objet en JavaScript ?
2. Que fait le mot-clé « new » avant l'appel d'une fonction constructeur ?
Tâches pratiques dans le jeu
- Clique dans l'ordre
Range les éléments de la création d'un objet dinosaure avec une méthode :
- Éditeur de code
Crée un objet dinosaur avec les propriétés name: 'Rexy', species: 'Tyrannosaurus Rex', age: 25 et isCarnivore: true, ainsi qu'un objet imbriqué stats qui a la propriété health: 95. Après avoir créé l'objet, ajoute-lui une propriété enclosure de valeur 'Zone A'. Affiche dans la console name avec la notation pointée et species avec la notation entre crochets.
- Tri horizontal
Range les éléments de la création d'un objet avec un littéral :
- Clique dans l'ordre
Range les éléments d'une déclaration d'objet avec des propriétés :
- Tri horizontal
Range les éléments d'une déclaration d'objet en JavaScript