Cours JavaScript et TypeScript · Module 1: Bases de JavaScript

Les fonctions

21 min de lecture
Dans cette leçon16

À Jurassic Park, l'équipe d'employés réalise diverses tâches spécialisées : le Dr Wu s'occupe de la génétique, l'équipe de sécurité surveille les clôtures, et les vétérinaires prennent soin de la santé des dinosaures. Chaque spécialiste réalise des tâches précises lorsqu'on le lui demande, sans avoir besoin d'expliquer à chaque fois exactement comment le faire.

En JavaScript, les fonctions fonctionnent de manière similaire - ce sont des blocs de code conçus pour réaliser des tâches précises. Les fonctions peuvent être définies une fois et appelées plusieurs fois, rendant le code plus modulaire, lisible et facile à maintenir.

Définir des fonctions

En JavaScript, il existe plusieurs façons de définir des fonctions. Commençons par la plus basique - la déclaration de fonction :

1// Syntaxe de base de la déclaration de fonction
2function functionName(parameter1, parameter2, ...) {
3  // Bloc de code à exécuter
4  return value; // Instruction facultative renvoyant une valeur
5}

Dans le contexte de Jurassic Park, nous pourrions créer une fonction pour vérifier la sécurité d'un enclos :

1// Fonction pour vérifier la sécurité d'un enclos
2function checkEnclosureSafety(powerLevel, fenceCondition, dinoSpecies) {
3  // Conditions de sécurité dépendant de l'espèce
4  let minPowerLevel;
5
6  if (dinoSpecies === "Tyrannosaurus" || dinoSpecies === "Velociraptor") {
7    minPowerLevel = 90; // Pour les prédateurs dangereux, nous exigeons un niveau d'alimentation élevé
8  } else if (dinoSpecies === "Dilophosaurus" || dinoSpecies === "Carnotaurus") {
9    minPowerLevel = 75; // Pour les petits prédateurs
10  } else {
11    minPowerLevel = 50; // Pour les herbivores
12  }
13
14  // Vérifier les conditions de sécurité
15  if (powerLevel < minPowerLevel) {
16    return "DANGEREUX : Niveau d'alimentation trop bas pour cette espèce !";
17  }
18
19  if (fenceCondition !== "intact") {
20    return "DANGEREUX : La clôture nécessite une réparation !";
21  }
22
23  return "SÛR : L'enclos remplit toutes les exigences de sécurité.";
24}
25
26// Exemples d'utilisation de la fonction
27let tRexInspectionResult = checkEnclosureSafety(85, "intact", "Tyrannosaurus");
28console.log(`Enclos du T-Rex : ${tRexInspectionResult}`); // "Enclos du T-Rex : DANGEREUX : Niveau d'alimentation trop bas pour cette espèce !"
29
30let triceratopsInspectionResult = checkEnclosureSafety(60, "intact", "Triceratops");
31console.log(`Enclos du Triceratops : ${triceratopsInspectionResult}`); // "Enclos du Triceratops : SÛR : L'enclos remplit toutes les exigences de sécurité."

Expressions de fonction

Une autre façon de définir des fonctions consiste à utiliser une expression de fonction, où une fonction est assignée à une variable :

1// Expression de fonction
2const functionName = function(parameter1, parameter2, ...) {
3  // Bloc de code à exécuter
4  return value; // Facultatif
5};

Exemple de Jurassic Park :

1// Fonction pour calculer le besoin quotidien en nourriture
2const calculateDailyFoodRequirement = function(species, weight, age) {
3  let baseFactor;
4
5  // Déterminer le facteur de base selon le régime alimentaire
6  if (["Tyrannosaurus", "Velociraptor", "Spinosaurus"].includes(species)) {
7    baseFactor = 0.10; // 10% du poids corporel pour les carnivores
8  } else if (["Allosaurus", "Carnotaurus", "Dilophosaurus"].includes(species)) {
9    baseFactor = 0.08; // 8% du poids corporel pour les carnivores plus petits
10  } else {
11    baseFactor = 0.15; // 15% du poids corporel pour les herbivores (mangent plus, mais une nourriture moins calorique)
12  }
13
14  // Correction selon l'âge (les jeunes spécimens mangent proportionnellement plus)
15  let ageFactor = age < 5 ? 1.5 : age < 10 ? 1.2 : 1.0;
16
17  // Calculer le besoin quotidien en nourriture en kg
18  let dailyRequirement = weight * baseFactor * ageFactor;
19
20  return Math.round(dailyRequirement * 10) / 10; // Arrondir à 1 décimale
21};
22
23// Exemples d'utilisation
24console.log(`Besoin quotidien en nourriture pour un jeune T-Rex : ${calculateDailyFoodRequirement("Tyrannosaurus", 2000, 3)} kg`);
25// "Besoin quotidien en nourriture pour un jeune T-Rex : 300 kg"
26
27console.log(`Besoin quotidien en nourriture pour un Stegosaurus adulte : ${calculateDailyFoodRequirement("Stegosaurus", 5000, 12)} kg`);
28// "Besoin quotidien en nourriture pour un Stegosaurus adulte : 750 kg"

Fonctions fléchées

Les fonctions fléchées sont une façon plus concise d'écrire des fonctions, introduite dans ES6 :

1// Syntaxe d'une fonction fléchée
2const functionName = (parameter1, parameter2, ...) => {
3  // Bloc de code
4  return value;
5};
6
7// Pour les fonctions simples avec une seule expression, tu peux omettre les accolades et le mot-clé return
8const simpleSum = (a, b) => a + b;

Exemple d'application à Jurassic Park :

1// Fonction fléchée pour classer les dinosaures
2const classifyDinosaur = (species, length, speed) => {
3  // Classification de la menace selon l'espèce, la taille et la vitesse
4  if (["Tyrannosaurus", "Spinosaurus"].includes(species) && length > 10) {
5    return "Menace la plus élevée - Classe A";
6  } else if (["Velociraptor", "Dilophosaurus"].includes(species) && speed > 30) {
7    return "Menace élevée - Classe B";
8  } else if (["Allosaurus", "Carnotaurus"].includes(species)) {
9    return "Menace moyenne - Classe C";
10  } else if (species.includes("raptor") || speed > 40) {
11    return "Menace accrue - Classe D";
12  } else {
13    return "Menace faible - Classe E";
14  }
15};
16
17// Fonctions fléchées simples sans bloc de code
18const isPredator = species => ["Tyrannosaurus", "Velociraptor", "Spinosaurus", "Allosaurus", "Carnotaurus", "Dilophosaurus"].includes(species);
19const estimateSpeed = (limbLength, mass) => Math.round(limbLength * 0.7 * (100 / mass));
20
21// Exemples d'utilisation
22console.log(classifyDinosaur("Tyrannosaurus", 12, 27)); // "Menace la plus élevée - Classe A"
23console.log(classifyDinosaur("Gallimimus", 2, 45)); // "Menace accrue - Classe D"
24console.log(isPredator("Stegosaurus")); // false
25console.log(estimateSpeed(2.5, 20)); // 9

Paramètres de fonction

Les fonctions peuvent accepter des paramètres, qui sont des variables locales disponibles à l'intérieur de la fonction :

Paramètres par défaut

Depuis ES6, nous pouvons définir des valeurs par défaut pour les paramètres :

1function setIncubatorTemperature(species, temperature = 37.5) {
2  console.log(`Température de l'incubateur réglée pour les œufs de ${species} à ${temperature}°C`);
3  // Suite du code...
4}
5
6setIncubatorTemperature("Velociraptor"); // "Température de l'incubateur réglée pour les œufs de Velociraptor à 37.5°C"
7setIncubatorTemperature("Triceratops", 36.2); // "Température de l'incubateur réglée pour les œufs de Triceratops à 36.2°C"

Paramètres du reste (rest)

Permettent de passer un nombre indéfini d'arguments sous forme de tableau :

1function monitorDinosaurs(...ids) {
2  console.log(`Surveillance de ${ids.length} dinosaures...`);
3
4  for (let id of ids) {
5    console.log(`Vérification du dinosaure #${id}...`);
6    // Code de surveillance...
7  }
8
9  return `Surveillance de ${ids.length} dinosaures terminée.`;
10}
11
12console.log(monitorDinosaurs(101, 102, 103, 104, 105));
13// Affichera :
14// "Surveillance de 5 dinosaures..."
15// "Vérification du dinosaure #101..."
16// "Vérification du dinosaure #102..."
17// "Vérification du dinosaure #103..."
18// "Vérification du dinosaure #104..."
19// "Vérification du dinosaure #105..."
20// "Surveillance de 5 dinosaures terminée."

Renvoyer des valeurs

Les fonctions peuvent renvoyer des valeurs à l'aide de l'instruction return :

1function analyzeDnaSample(sample) {
2  // Code d'analyse de l'échantillon...
3
4  if (!sample || sample.length < 10) {
5    return { success: false, message: "Matériel génétique insuffisant." };
6  }
7
8  // Simulation de l'analyse
9  const species = ["Tyrannosaurus", "Triceratops", "Velociraptor", "Stegosaurus", "Brontosaurus"];
10  const randomIndex = Math.floor(Math.random() * species.length);
11
12  return {
13    success: true,
14    species: species[randomIndex],
15    dnaPurity: Math.round(Math.random() * 50 + 50), // 50-100%
16    completeness: Math.round(Math.random() * 40 + 60), // 60-100%
17    message: "Analyse terminée avec succès."
18  };
19}
20
21const analysisResult = analyzeDnaSample("ACGTAAGTCCTGAT");
22console.log(analysisResult);
23// Exemple de sortie :
24// {
25//   success: true,
26//   species: "Velociraptor",
27//   dnaPurity: 87,
28//   completeness: 75,
29//   message: "Analyse terminée avec succès."
30// }
31
32if (analysisResult.success) {
33  console.log(`ADN de ${analysisResult.species} identifié avec une pureté de ${analysisResult.dnaPurity}%`);
34} else {
35  console.log(`Erreur d'analyse : ${analysisResult.message}`);
36}

Portée des variables

Les variables définies à l'intérieur d'une fonction sont locales à cette fonction et ne sont pas accessibles de l'extérieur :

1function prepareJurassicIncident() {
2  // Variable locale, non accessible en dehors de la fonction
3  let secretSystemCode = "TRex1993";
4  console.log(`Code généré à l'intérieur de la fonction : ${secretSystemCode}`);
5  return "Incident préparé.";
6}
7
8prepareJurassicIncident();
9// Tenter d'accéder à la variable locale en dehors de la fonction provoquera une erreur
10// console.log(secretSystemCode); // ReferenceError: secretSystemCode is not defined
11
12// Les variables définies en dehors d'une fonction sont accessibles à l'intérieur
13let jurassicParkLocation = "Isla Nublar";
14
15function displayParkInfo() {
16  // Accès à la variable externe
17  console.log(`Jurassic Park est situé sur l'île : ${jurassicParkLocation}`);
18
19  // Variable locale
20  let dinosaurCount = 200;
21  console.log(`Nombre actuel de dinosaures : ${dinosaurCount}`);
22}
23
24displayParkInfo();
25// console.log(dinosaurCount); // ReferenceError: dinosaurCount is not defined

Fonctions imbriquées

Les fonctions peuvent être définies à l'intérieur d'autres fonctions :

1function conductScientificResearch(species) {
2  console.log(`Démarrage de la recherche scientifique sur l'espèce : ${species}`);
3
4  // Fonction imbriquée - accessible uniquement à l'intérieur de conductScientificResearch
5  function analyzeSample() {
6    console.log(`Analyse de l'échantillon d'ADN de ${species}...`);
7    return "Analyse terminée";
8  }
9
10  // Autre fonction imbriquée
11  function simulateGrowth() {
12    console.log(`Simulation de la croissance et du développement de ${species}...`);
13    return "Simulation terminée";
14  }
15
16  // Appeler les fonctions imbriquées
17  const analysisResult = analyzeSample();
18  const simulationResult = simulateGrowth();
19
20  return {
21    species,
22    analysisResult,
23    simulationResult,
24    researchDate: new Date().toISOString()
25  };
26}
27
28const researchReport = conductScientificResearch("Velociraptor");
29console.log(researchReport);
30// Les fonctions imbriquées ne sont pas accessibles en dehors de la fonction externe
31// analyzeSample(); // ReferenceError: analyzeSample is not defined

Fonctions d'ordre supérieur

En JavaScript, les fonctions sont des objets de première classe, ce qui signifie qu'elles peuvent être passées comme arguments à d'autres fonctions ou renvoyées par des fonctions :

1// Fonction acceptant une autre fonction comme paramètre
2function monitorEnclosure(enclosureId, alarmFunction) {
3  console.log(`Surveillance de l'enclos #${enclosureId}`);
4
5  // Simulation d'un problème
6  const anomalyDetected = Math.random() > 0.7;
7
8  if (anomalyDetected) {
9    // Appeler la fonction passée lorsqu'un problème est détecté
10    alarmFunction(`Anomalie détectée dans l'enclos #${enclosureId} !`);
11  }
12
13  return { enclosureId, status: anomalyDetected ? "Anomaly" : "Normal" };
14}
15
16// Fonctions qui peuvent être passées comme arguments
17function soundAlarm(message) {
18  console.log(`ALARME SONORE : ${message}`);
19}
20
21function visualAlarm(message) {
22  console.log(`ALARME VISUELLE : ${message}`);
23}
24
25function staffNotifications(message) {
26  console.log(`NOTIFICATION SMS : ${message}`);
27}
28
29// Utiliser la fonction d'ordre supérieur avec différentes fonctions d'alarme
30monitorEnclosure(1, soundAlarm);
31monitorEnclosure(2, visualAlarm);
32monitorEnclosure(3, staffNotifications);
33
34// Nous pouvons aussi passer une fonction anonyme
35monitorEnclosure(4, function(message) {
36  console.log(`PROCÉDURE D'URGENCE : ${message}`);
37  console.log("Lancement du protocole d'évacuation...");
38});
39
40// Ou une fonction fléchée
41monitorEnclosure(5, message => console.log(`RAPPORT DE DIAGNOSTIC : ${message}`));

Fonction renvoyant une fonction

1// Fonction créant et renvoyant une autre fonction
2function createSpeciesMonitor(species) {
3  // Nous renvoyons une nouvelle fonction adaptée à une espèce précise
4  return function(action) {
5    const actionTime = new Date().toLocaleTimeString();
6    console.log(`[${actionTime}] ${species}: ${action}`);
7
8    // Logique supplémentaire dépendant de l'espèce
9    if (["Tyrannosaurus", "Velociraptor", "Dilophosaurus"].includes(species) && action.includes("près de la clôture")) {
10      console.log(`ATTENTION ! Le prédateur dangereux ${species} est près de la clôture !`);
11    }
12  };
13}
14
15// Créer des moniteurs pour différentes espèces
16const tRexMonitor = createSpeciesMonitor("Tyrannosaurus");
17const triceratopsMonitor = createSpeciesMonitor("Triceratops");
18
19// Utiliser les fonctions renvoyées
20tRexMonitor("Se déplace vers le sud");
21tRexMonitor("Se rapproche près de la clôture");
22triceratopsMonitor("Broute dans la partie nord de l'enclos");

Expressions de fonction immédiatement invoquées (IIFE)

Une IIFE (Immediately Invoked Function Expression) est une fonction qui est définie et appelée immédiatement :

1// Structure d'une IIFE
2(function() {
3  // Code de la fonction...
4})();
5
6// IIFE avec paramètres
7(function(name) {
8  console.log(`Initialisation du système : ${name}`);
9})("Jurassic Park");

Les IIFE sont utiles pour créer une portée privée et éviter de polluer l'objet global :

1// Initialisation du système de Jurassic Park à l'aide d'une IIFE
2const jurassicParkSystem = (function() {
3  // Variables privées, non accessibles de l'extérieur
4  const securityCodes = {
5    mainGates: "GATES1993",
6    laboratory: "INGEN2015",
7    powerSystem: "NEDRY1992"
8  };
9
10  let systemStatus = "offline";
11  let securityLevel = 0;
12
13  // Fonctions privées
14  function validateCode(providedCode, requiredCode) {
15    return providedCode === requiredCode;
16  }
17
18  // Interface publique - seules ces fonctions seront accessibles de l'extérieur
19  return {
20    startSystem: function() {
21      systemStatus = "online";
22      securityLevel = 3;
23      console.log("Système de Jurassic Park démarré.");
24      return true;
25    },
26
27    checkStatus: function() {
28      return {
29        status: systemStatus,
30        securityLevel,
31        updateTime: new Date().toISOString()
32      };
33    },
34
35    grantAccess: function(area, code) {
36      if (!validateCode(code, securityCodes[area])) {
37        console.log(`Accès refusé à la zone : ${area}`);
38        return false;
39      }
40      console.log(`Accès accordé à la zone : ${area}`);
41      return true;
42    }
43  };
44})();
45
46// Utiliser l'interface publique
47jurassicParkSystem.startSystem();
48console.log(jurassicParkSystem.checkStatus());
49jurassicParkSystem.grantAccess("mainGates", "GATES1993"); // true
50jurassicParkSystem.grantAccess("laboratory", "wrong code"); // false
51
52// Tenter d'accéder aux variables privées échouera
53// console.log(jurassicParkSystem.securityCodes); // undefined
54// console.log(jurassicParkSystem.validateCode); // undefined

Récursion

La récursion est une technique où une fonction s'appelle elle-même :

1// Fonction récursive simulant la reproduction des dinosaures
2function simulateReproduction(initialPopulation, yearsAhead, growthRate = 1.5) {
3  // Condition de fin de la récursion
4  if (yearsAhead <= 0) {
5    return initialPopulation;
6  }
7
8  // Calculer la nouvelle population après une année
9  const newPopulation = Math.round(initialPopulation * growthRate);
10
11  console.log(`Année ${yearsAhead} avant la fin de la simulation. Population : ${newPopulation}`);
12
13  // Appel récursif avec la nouvelle population et le compteur d'années décrémenté
14  return simulateReproduction(newPopulation, yearsAhead - 1, growthRate);
15}
16
17// Population initiale : 2 dinosaures, simulation pour 5 ans
18const finalPopulation = simulateReproduction(2, 5);
19console.log(`Population finale après 5 ans : ${finalPopulation}`);
20
21// Résultat :
22// Année 5 avant la fin de la simulation. Population : 3
23// Année 4 avant la fin de la simulation. Population : 5
24// Année 3 avant la fin de la simulation. Population : 8
25// Année 2 avant la fin de la simulation. Population : 12
26// Année 1 avant la fin de la simulation. Population : 18
27// Population finale après 5 ans : 18

Il est important d'avoir toujours une condition de fin de récursion pour éviter des appels infinis, qui peuvent provoquer une erreur de débordement de pile (stack overflow).

Hoisting

Le hoisting est un comportement de JavaScript qui « déplace » les déclarations au sommet de leur portée :

1// Nous pouvons appeler une fonction avant sa déclaration grâce au hoisting
2console.log(checkParkSafety()); // "Parc sûr"
3
4// La déclaration de fonction est déplacée au sommet
5function checkParkSafety() {
6  return "Parc sûr";
7}
8
9// Cependant, les expressions de fonction ne sont pas entièrement hissées
10// console.log(calculateRisk()); // Erreur : calculateRisk is not a function
11
12// Seule la déclaration de variable est hissée, pas sa valeur
13var calculateRisk = function() {
14  return "Risque faible";
15};
16
17// De même avec let et const - elles sont hissées mais non initialisées
18// console.log(analyzeData); // ReferenceError: Cannot access 'analyzeData' before initialization
19let analyzeData = function() {
20  return "Analyse terminée";
21};

Fermetures (closures)

Une fermeture est créée lorsqu'une fonction interne a accès à la portée de la fonction externe, même après que celle-ci a terminé son exécution :

1function createDinosaurCounter(roomName) {
2  let dinosaurCount = 0;
3
4  // La fonction interne crée une fermeture
5  function updateCounter(change) {
6    dinosaurCount += change;
7    console.log(`${roomName}: Nombre actuel de dinosaures : ${dinosaurCount}`);
8    return dinosaurCount;
9  }
10
11  return {
12    addDinosaur: function() {
13      return updateCounter(1);
14    },
15    removeDinosaur: function() {
16      return updateCounter(-1);
17    },
18    getDinosaurCount: function() {
19      return dinosaurCount;
20    }
21  };
22}
23
24// Créer deux compteurs indépendants pour différentes pièces
25const enclosureACounter = createDinosaurCounter("Enclos A");
26const enclosureBCounter = createDinosaurCounter("Enclos B");
27
28enclosureACounter.addDinosaur(); // "Enclos A: Nombre actuel de dinosaures : 1"
29enclosureACounter.addDinosaur(); // "Enclos A: Nombre actuel de dinosaures : 2"
30enclosureBCounter.addDinosaur(); // "Enclos B: Nombre actuel de dinosaures : 1"
31enclosureACounter.removeDinosaur();  // "Enclos A: Nombre actuel de dinosaures : 1"

Les fermetures sont extrêmement utiles pour créer des fonctions fabriques, encapsuler des données et implémenter des modèles de conception.

Bonnes pratiques lors de l'utilisation des fonctions

  1. Une fonction, une tâche : Les fonctions devraient être conçues pour réaliser une tâche précise. Cela facilite les tests, le débogage et la maintenance du code.

  2. Noms de fonctions descriptifs : Utilise des noms de fonctions clairs et descriptifs qui indiquent leur objectif (p. ex. loginUser au lieu de uFunc1).

  3. Limite le nombre de paramètres : Essaie de limiter le nombre de paramètres. Si une fonction requiert de nombreux paramètres, envisage d'utiliser un objet d'options :

1// Au lieu de :
2function configureSecuritySystem(powerLevel, sensorSensitivity, reactionTime, operationMode, notifications) {
3  //
4}
5
6// Utilise :
7function configureSecuritySystem(options) {
8  const {
9    powerLevel = 100,
10    sensorSensitivity = "high",
11    reactionTime = 5,
12    operationMode = "automatic",
13    notifications = true
14  } = options;
15
16  //
17}
18
19// Appel :
20configureSecuritySystem({
21  powerLevel: 90,
22  reactionTime: 3,
23  operationMode: "manual"
24});
  1. Évite les effets de bord : Essaie de t'assurer que les fonctions ne modifient pas de variables en dehors de leur portée ni les objets et tableaux qu'on leur passe (la fonction reçoit une référence vers le même objet, donc la modification est visible à l'extérieur).

  2. Conventions de valeur de retour : Sois cohérent dans le renvoi des valeurs. Évite les fonctions qui renvoient parfois une valeur et parfois non.

  3. Gestion des erreurs : Prends toujours en compte les erreurs potentielles et gère-les de manière appropriée à l'aide de blocs try-catch ou en renvoyant des objets de statut.

1function cloneDinosaur(dna) {
2  try {
3    if (!dna || dna.length < 100) {
4      throw new Error("ADN insuffisant pour le clonage");
5    }
6
7    // Code de clonage...
8
9    return {
10      success: true,
11      dinosaur: { species: "Velociraptor", id: "VR-" + Math.floor(Math.random() * 1000) }
12    };
13  } catch (error) {
14    console.error(`Erreur de clonage : ${error.message}`);
15    return {
16      success: false,
17      error: error.message
18    };
19  }
20}

L'avenir de JavaScript - TC39 et les propositions de développement du langage

Tout comme l'ADN des dinosaures évoluait constamment pour s'adapter à un environnement changeant, JavaScript subit lui aussi un processus continu d'évolution. Derrière ce processus se trouve TC39 - le comité technique responsable du développement du langage JavaScript.

Qu'est-ce que TC39 ?

TC39 (Technical Committee 39) est un groupe d'experts qui gère le développement de la spécification ECMAScript (le nom officiel du standard JavaScript). TC39 comprend des représentants d'entreprises comme Google, Mozilla, Apple, Microsoft, ainsi que d'autres organisations et des experts indépendants.

Tout comme le conseil scientifique de Jurassic Park décide quelles espèces de dinosaures seront élevées et comment elles seront gérées, TC39 décide quelles nouvelles fonctionnalités seront ajoutées à JavaScript et sous quelle forme.

Le processus de proposition - Étapes 0-4

Chaque nouvelle fonctionnalité en JavaScript passe par les étapes 0, 1, 2, 2.7, 3 et 4, de l'idée à l'implémentation :

Étape 0 - Strawman

L'étape la plus précoce - c'est comme la première esquisse d'une nouvelle espèce de dinosaure sur papier. N'importe qui peut soumettre une idée. Il n'y a aucune exigence formelle ; c'est simplement un endroit pour partager des idées.

Étape 1 - Proposal

Le comité a décidé que l'idée valait la peine d'être considérée. C'est comme la phase où les scientifiques de Jurassic Park ont décidé qu'il valait la peine d'envisager sérieusement le clonage d'une espèce précise. À cette étape :

  • Le problème que la proposition vise à résoudre est identifié
  • Une solution générale est décrite
  • Les défis potentiels sont identifiés

Étape 2 - Draft

La proposition dispose désormais d'une spécification technique préliminaire. C'est comme un plan génétique détaillé et des procédures d'élevage pour un nouveau dinosaure. À cette étape :

  • La syntaxe est largement façonnée
  • La sémantique est formellement décrite
  • La fonctionnalité devrait à terme être incluse dans le langage

Étape 2.7 - Spécification approuvée (depuis 2024)

Le comité a approuvé la spécification, et les tests de conformité (test262) sont en cours d'écriture. Les navigateurs commencent l'implémentation une fois ces tests écrits.

Étape 3 - Candidate

La spécification est complète et attend les retours d'implémentation. C'est comme les premières tentatives de clonage - nous avons un plan complet, maintenant nous le testons en pratique. À cette étape :

  • Les navigateurs et environnements commencent à implémenter la fonctionnalité
  • Les retours des développeurs sont collectés
  • Seules des corrections mineures sont apportées

Étape 4 - Finished

La proposition est prête à être incluse dans la spécification officielle ECMAScript ! C'est comme le moment où un nouveau dinosaure éclôt avec succès et est prêt à être présenté dans le parc. À cette étape :

  • Au moins deux implémentations indépendantes existent
  • Les tests sont écrits et acceptés
  • La fonctionnalité sera incluse dans la prochaine version d'ECMAScript

Propositions intéressantes à diverses étapes

Examinons quelques propositions fascinantes qui pourraient changer la façon dont nous écrivons du code JavaScript :

Opérateur pipeline (|>) - Étape 2

L'opérateur pipeline permet d'enchaîner des opérations de manière plus lisible, semblable aux canaux de transport d'eau de Jurassic Park :

1// Sans l'opérateur pipeline
2const result = Math.round(Math.max(5, 10, 15) * 2);
3
4// Avec l'opérateur pipeline (% représente le résultat de l'étape précédente)
5const result = Math.max(5, 10, 15)
6  |> % * 2
7  |> Math.round(%);
8
9// Exemple avec le système de sécurité du parc
10const securityStatus = fetchSensorData()
11  |> filterActiveSensors(%)
12  |> analyzeThreatLevel(%)
13  |> generateSecurityReport(%);

Records & Tuples - proposition retirée

Records & Tuples, des structures de données immuables comparées par valeur, ont atteint l'étape 2, mais en 2025 le comité a retiré la proposition. C'est un bon exemple : toutes les propositions n'arrivent pas dans le langage.

Pattern Matching - Étape 1

Un puissant mécanisme de filtrage par motif qui rend le code conditionnel plus lisible. C'est comme un système de classification des dinosaures - nous pouvons précisément associer des actions à différents types :

1// Au lieu de nombreuses instructions if/else ou switch
2const handleDinosaur = (dino) => {
3  match (dino) {
4    when ({ species: "Tyrannosaurus Rex", health: health }) if (health < 50) -> {
5      return "Appelez le vétérinaire pour le T-Rex !";
6    }
7    when ({ diet: "carnivore", escaped: true }) -> {
8      return "ALARME ! Un prédateur s'est échappé !";
9    }
10    when ({ species: "Velociraptor" }) -> {
11      return "Vérifiez la sécurité de l'enclos";
12    }
13    when ({ health: h }) if (h > 90) -> {
14      return "Dinosaure en excellente condition";
15    }
16    default -> {
17      return "Procédure de surveillance standard";
18    }
19  }
20};

Décorateurs - Étape 3

Les décorateurs permettent de modifier les classes et leurs membres de manière déclarative. C'est comme le système de marquage et de puces pour les dinosaures - nous ajoutons des fonctionnalités supplémentaires sans modifier la structure de base :

1// Décorateur pour journaliser les appels de méthodes
2function log(method, context) {
3  return function (...args) {
4    console.log(`Appel de ${context.name} avec les arguments : ${JSON.stringify(args)}`);
5    const result = method.apply(this, args);
6    console.log(`Résultat : ${result}`);
7    return result;
8  };
9}
10
11class DinosaurMonitor {
12  @log
13  checkHealth(dinosaurId) {
14    // Vérification de la santé
15    return "healthy";
16  }
17
18  @log
19  feedDinosaur(dinosaurId, foodAmount) {
20    // Nourrissage du dinosaure
21    return "fed";
22  }
23}
24
25// Chaque appel de méthode sera automatiquement journalisé !
26const monitor = new DinosaurMonitor();
27monitor.checkHealth("TREX-001");
28// Console: Appel de checkHealth avec les arguments : ["TREX-001"]
29// Console: Résultat : healthy

Comment suivre le développement du langage ?

Si tu veux rester à jour avec l'évolution de JavaScript, de la même manière que les scientifiques de Jurassic Park surveillent l'évolution de leurs dinosaures, tu peux :

  1. Dépôt GitHub de TC39 : https://github.com/tc39/proposals

    • Liste complète de toutes les propositions avec leurs statuts actuels
    • Discussions et documentation technique
  2. Notes de réunion de TC39 : https://github.com/tc39/notes

    • Notes des réunions du comité
    • Aperçu du processus de décision
  3. Can I Use : https://caniuse.com

    • Vérifier la prise en charge des nouvelles fonctionnalités par les navigateurs
    • Planifier quand utiliser en toute sécurité une nouvelle fonctionnalité
  4. Babel : https://babeljs.io

    • Possibilité d'expérimenter dès maintenant avec de nouvelles fonctionnalités
    • Transpiler du code moderne vers des versions prises en charge par les anciens navigateurs
  5. Site web de TC39 : https://tc39.es

    • Site officiel du comité
    • Documentation et règles du processus

Pourquoi suivre les propositions de TC39 ?

  1. Pérennité - connaître les fonctionnalités à venir permet de planifier l'architecture de l'application en pensant à l'avenir
  2. Influence sur le langage - la communauté peut soumettre des retours et influencer la forme des nouvelles fonctionnalités
  3. Avantage concurrentiel - la connaissance des dernières capacités du langage fait de toi un développeur plus précieux
  4. Meilleure qualité de code - les nouvelles fonctionnalités offrent souvent des façons plus propres et plus sûres de résoudre des problèmes

Tout comme Jurassic Park évolue constamment, en ajoutant de nouvelles espèces et en améliorant les systèmes de sécurité, JavaScript se développe lui aussi en permanence. Comprendre le processus TC39 et suivre les nouvelles propositions, c'est comme avoir une carte génétique de l'avenir du langage - cela nous permet de nous préparer à ce qui arrive et de façonner cet avenir grâce à une participation active de la communauté.

Résumé

Les fonctions en JavaScript, tout comme les équipes spécialisées de Jurassic Park, te permettent de :

  1. Organiser le code - regrouper la logique liée en un seul endroit
  2. Réutiliser - définir une logique une fois et l'utiliser plusieurs fois
  3. Abstraire - cacher les détails d'implémentation derrière une interface simple
  4. Modulariser - construire des systèmes complexes à partir de composants plus simples et indépendants

Concepts clés sur les fonctions :

  • Différentes façons de les définir : déclarations, expressions, fonctions fléchées
  • Paramètres et arguments, y compris les paramètres par défaut et du reste
  • Renvoyer des valeurs
  • Portée des variables
  • Fonctions d'ordre supérieur
  • Récursion
  • Fermetures

Nous avons aussi découvert le mécanisme TC39 et le processus de développement de JavaScript - des propositions à l'Étape 0 jusqu'aux implémentations finies à l'Étape 4. Comprendre ce processus nous permet de rester à jour avec l'évolution du langage et de nous préparer à l'avenir de la programmation JavaScript.

Dans la prochaine leçon, tu réuniras tout ce que tu as appris dans le projet final.

Code de cette leçon : index.js
1// Fonctions en JavaScript
2// Différentes façons de définir et d'utiliser les fonctions
3
4// === Déclaration de fonction ===
5console.log("=== Déclaration de fonction ===");
6
7function checkHealth(name, health) {
8  if (health > 80) {
9    return name + " - EXCELLENT";
10  } else if (health > 50) {
11    return name + " - BON";
12  } else {
13    return name + " - NÉCESSITE DES SOINS";
14  }
15}
16
17console.log(checkHealth("T-Rex", 95));
18console.log(checkHealth("Raptor", 72));
19console.log(checkHealth("Brachio", 45));
20
21// === Paramètres par défaut ===
22console.log("\n=== Paramètres par défaut ===");
23
24function feedDinosaur(name, amount = 50) {
25  console.log(name + " nourri : " + amount + " kg");
26}
27
28feedDinosaur("T-Rex", 200);
29feedDinosaur("Compy"); // utilisera la valeur par défaut 50
30
31// === Fonctions fléchées ===
32console.log("\n=== Fonctions fléchées ===");
33
34const calcAge = (discoveryYear) => 2024 - discoveryYear;
35
36console.log("T-Rex découvert en 1905, années de recherche:", calcAge(1905));
37console.log("Triceratops découvert en 1889, années de recherche:", calcAge(1889));
38
39// Fonction fléchée sur plusieurs lignes
40const dinoProfile = (name, weight, diet) => {
41  const threat = diet === "carnivore" ? "ÉLEVÉE" : "FAIBLE";
42  return name + " (" + weight + "kg) - Menace : " + threat;
43};
44
45console.log(dinoProfile("T-Rex", 7000, "carnivore"));
46console.log(dinoProfile("Brachio", 80000, "herbivore"));
47
48// === Fonctions comme arguments (callback) ===
49console.log("\n=== Callback ===");
50
51const dinosaurs = ["T-Rex", "Velociraptor", "Triceratops"];
52
53dinosaurs.forEach(function(dino, index) {
54  console.log((index + 1) + ". " + dino);
55});
56
57// Avec une fonction fléchée
58const weights = [7000, 15, 8000, 80000];
59const large = weights.filter(w => w > 5000);
60console.log("\nGrands dinosaures (>5000kg):", large);
61
62// === Return ===
63console.log("\n=== Fonction avec return ===");
64
65function findLargest(array) {
66  let max = array[0];
67  for (const value of array) {
68    if (value > max) {
69      max = value;
70    }
71  }
72  return max;
73}
74
75console.log("Le plus lourd:", findLargest(weights), "kg");
76
77// Ta mission :
78// 1. Crée une fonction qui calcule la moyenne d'un tableau
79// 2. Utilise une fonction fléchée pour filtrer les données
80// 3. Écris une fonction avec un paramètre par défaut
81

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. 1. Qu'est-ce qu'un paramètre par défaut dans une fonction ?

  2. 2. Que fait un moteur JavaScript moderne (par exemple V8) d'un fragment de code exécuté très souvent (code « chaud ») ?

  3. 3. Que renvoie l'expression 0 === false en JavaScript ?

  4. 4. Quelle couche d'une application web est responsable de la communication avec le serveur ?

  5. 5. Quelle est la PREMIÈRE étape du processus de débogage en JavaScript ?

  6. 6. Quelle portée ont les variables déclarées avec let et const ?

Tâches pratiques dans le jeu

  • Éditeur de code

    Écris une fonction calculateFoodPortion(diet, weightKg) qui renvoie la portion quotidienne de nourriture en kg : 5 % du poids pour le régime 'carnivore', 3 % pour 'herbivore' et 4 % pour 'omnivore'. Appelle-la pour un T-Rex ('carnivore', 8000) et affiche le résultat dans la console.

  • Tri horizontal

    Classe les éléments de l'appel de fonction avec des arguments :

  • Tri vertical

    Classe les étapes de définition et d'appel des fonctions en JavaScript :

  • Clique dans l'ordre

    Classe les éléments de la déclaration d'une fonction dans le bon ordre :

  • Éditeur de code

    Écris une fonction calculateFossilAge(currentYear, fossilYear) qui renvoie l'âge du fossile en millions d'années : (currentYear - fossilYear) / 1000000. Écris les années avant notre ère comme des nombres négatifs. Appelle-la pour un T-Rex (2024, -68000000) et affiche le résultat dans la console.

  • Clique dans l'ordre

    Classe les éléments de la fonction fléchée dans le bon ordre :

  • Éditeur de code

    Tu as les données d'un enclos : const voltage = 8500 et const fenceHealth = 40. Crée une variable isSafe qui vaut true quand voltage > 5000 et en même temps fenceHealth > 50 (utilise &&), et une variable needsAttention qui vaut true quand fenceHealth < 50 ou voltage === 0 (utilise ||). Affiche les deux dans la console.

Articles utiles