Chapitre 24
UA 5 : PROGRAMMATION EN JAVASCRIPT (partie 2/2)
Lecture : 14 minQuiz de 10 questions
## Objectifs et prérequis
**Objectifs** : À la fin de ce chapitre, l’élève sera capable de :
- Déclarer et appeler des fonctions JavaScript, avec ou sans paramètres, et comprendre le rôle du mot‑clé `return`.
- Utiliser les fonctions fléchées et les fonctions anonymes comme gestionnaires d’évènements.
- Associer un évènement DOM (click, submit, change…) à une fonction de rappel et empêcher le comportement par défaut lorsqu’il est nécessaire.
- Concevoir, coder et tester un petit convertisseur (température, monnaie ou unités) en HTML/CSS/JS, en séparant la structure, la présentation et la logique.
- Déboguer un script simple à l’aide de la console du navigateur et identifier les erreurs de syntaxe ou de logique les plus fréquentes.
**Prérequis** : Maîtrise des bases du langage JavaScript (variables, types primitifs, opérateurs, structures de contrôle `if…else`, boucles `for`/`while`), connaissance minimale du DOM (sélection d’éléments avec `document.getElementById` ou `querySelector`), et capacité à écrire une page HTML valide.
---
## Introduction contextualisée
Dans les applications web modernes, la logique métier est souvent déléguée au côté client grâce à JavaScript. Les fonctions permettent d’encapsuler des traitements réutilisables, tandis que les évènements rendent la page interactive en réagissant aux actions de l’utilisateur (clic, saisie, soumission de formulaire…). Le convertisseur constitue un projet typique du programme de Première : il combine la manipulation du DOM, la gestion d’évènements et l’application de formules de conversion mathématiques. Maîtriser ces deux leçons prépare l’élève à l’épreuve pratique du Probatoire, où il devra produire un petit programme fonctionnel, commenté et exempt d’erreurs classiques.
---
## I. Leçon 20 : Fonctions et évènements en JavaScript
### 20.1 Définition d’une fonction
> **Une fonction** est un bloc d’instructions nommé qui peut être appelé plusieurs fois, éventuellement avec des paramètres, et qui peut renvoyer une valeur grâce à l’instruction `return`.
**Propriétés**
- Une fonction sans `return` renvoie `undefined`.
- Les paramètres sont passés par valeur ; lorsqu’un objet est passé, la valeur transmise est la référence vers cet objet.
- La portée des variables déclarées avec `let` ou `const` à l’intérieur d’une fonction est locale à cette fonction.
**Démonstration** : Considérons la fonction suivante :
```javascript
function somme(a, b) {
return a + b;
}
```
L’appel `somme(3, 4)` exécute le corps, calcule `3 + 4 = 7` et renvoie cette valeur grâce à `return`. Si l’on enlève `return`, la fonction renvoie `undefined` :
```javascript
function sommeSansReturn(a, b) {
a + b; // aucune instruction de retour
}
console.log(sommeSansReturn(3, 4)); // → undefined
```
### 20.2 Syntaxe, paramètres et retour
**Syntaxe générale**
```javascript
function nomFonction(param1, param2, ...) {
// corps
return valeur; // optionnel
}
```
- Les paramètres peuvent avoir des valeurs par défaut : `function salut(nom = "Invité") { … }`.
- Le mot‑clé `arguments` (objet semblable à un tableau) donne accès à tous les arguments passés, même non déclarés.
**Exemple 1 – Fonction simple**
Objectif : retourner le carré d’un nombre.
```javascript
function carre(x) {
return x * x;
}
console.log(carre(5)); // → 25
```
**Exemple 2 – Fonction avec valeur par défaut et plusieurs paramètres**
Objectif : calculer le prix TTC d’un article sachant le prix HT et le taux de TVA (défaut 0,1925).
```javascript
function prixTTC(ht, tva = 0.1925) {
return ht * (1 + tva);
}
console.log(prixTTC(1000)); // → 1192.5
console.log(prixTTC(1000, 0.09)); // → 1090
```
### 20.3 Fonctions anonymes et flèches
> **Fonction anonyme** : fonction sans nom, souvent utilisée comme valeur d’une variable ou comme argument d’une autre fonction.
> **Fonction fléchée** : syntaxe concise `() => { … }` qui lie lexicalement `this`.
**Exemple 1 – Fonction anonyme comme gestionnaire d’évènement**
```javascript
document.getElementById("monBouton").onclick = function() {
alert("Bouton cliqué !");
};
```
**Exemple 2 – Même comportement avec une flèche**
```javascript
document.getElementById("monBouton").onclick = () => {
alert("Bouton cliqué !");
};
```
### 20.4 Gestion des évènements
> **Écouteur d’évènement** : méthode `addEventListener(type, fonction, options)` qui enregistre une fonction de rappel à exécuter lorsqu’un évènement spécifié se produit sur un nœud DOM.
**Propriétés importantes**
- **Propagation** : par défaut, l’évènement remonte (bubbling) du nœud cible vers ses ancêtres. On peut arrêter la propagation avec `event.stopPropagation()`.
- **Action par défaut** : certains évènements (comme la soumission d’un formulaire) déclenchent une action du navigateur ; `event.preventDefault()` l’annule.
**Démonstration** – Empêcher la soumission d’un formulaire tant qu’un champ est vide :
```html
<form id="monForm">
<input type="text" id="nom" placeholder="Nom">
<button type="submit">Envoyer</button>
</form>
```
```javascript
document.getElementById("monForm").addEventListener("submit", function(e) {
const nom = document.getElementById("nom").value.trim();
if (nom === "") {
e.preventDefault(); // annule l’envoi
alert("Veuillez saisir votre nom.");
}
});
```
### 20.5 Exemples entièrement résolus
#### Exemple A – Fonction qui change la couleur d’un paragraphe au clic
**HTML**
```html
<p id="texte">Cliquez ici pour changer de couleur.</p>
<button id="btn">Changer couleur</button>
```
**JS**
```javascript
function changerCouleur() {
const p = document.getElementById("texte");
p.style.color = p.style.color === "red" ? "black" : "red";
}
document.getElementById("btn").addEventListener("click", changerCouleur);
```
**Étapes**
1. Au chargement, le script enregistre `changerCouleur` comme gestionnaire du `click` sur le bouton.
2. Lorsque l’utilisateur clique, la fonction lit la couleur actuelle du paragraphe.
3. Si elle vaut `"red"`, elle la remet à `"black"` ; sinon, elle la passe à `"red"`.
4. Le navigateur applique immédiatement le nouveau style.
#### Exemple B – Fonction anonyme qui valide un champ email grâce à une expression régulière
**HTML**
```html
<input type="email" id="mail">
<span id="msg"></span>
```
**JS**
```javascript
document.getElementById("mail").addEventListener("input", function() {
const email = this.value;
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
document.getElementById("msg").textContent =
regex.test(email) ? "Adresse valide" : "Adresse invalide";
});
```
**Étapes**
1. À chaque modification du champ (`input` event), la fonction anonyme s’exécute.
2. Elle récupère la valeur du champ, la teste contre l’expression régulière qui vérifie la présence d’un `@` suivi d’un point.
3. Selon le résultat, elle met à jour le texte du `<span>` pour informer l’utilisateur.
---
## II. Leçon 21 : Programmation d’un convertisseur
### 21.1 Analyse du besoin
Un convertisseur doit :
- Présenter deux unités (ex. : Celsius ↔ Fahrenheit, Euro ↔ Franc CFA).
- Permettre à l’utilisateur de saisir une valeur dans l’une des unités.
- Calculer et afficher automatiquement la valeur correspondante dans l’autre unité.
- Gérer les erreurs de saisie (vide, non numérique).
### 21.2 Structure HTML de base
```html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Convertisseur de température</title>
<style>
body { font-family: Arial, sans-serif; margin: 2rem; }
.block { margin-bottom: 1rem; }
label { display: block; margin-bottom: .3rem; }
input, output { width: 10rem; padding: .3rem; font-size: 1rem; }
</style>
</head>
<body>
<h1>Convertisseur Celsius ↔ Fahrenheit</h1>
<div class="block">
<label for="celsius">Celsius (°C)</label>
<input type="number" id="celsius" step="0.01">
</div>
<div class="block">
<label for="fahrenheit">Fahrenheit (°F)</label>
<output id="fahrenheit"></output>
</div>
<script src="convertisseur.js"></script>
</body>
</html>
```
### 21.3 Logique JS du convertisseur
> **Formule de conversion** : $F = \frac{9}{5}C + 32$ et son inverse $C = \frac{5}{9}(F - 32)$.
Nous choisirons de mettre à jour le champ opposé dès que l’utilisateur quitte le champ saisie (`blur`) ou lorsqu’il appuie sur `Enter`.
**Fichier `convertisseur.js`**
```javascript
// références aux éléments du DOM
const celsiusInput = document.getElementById("celsius");
const fahrenheitOutput = document.getElementById("fahrenheit");
/**
* Convertit Celsius → Fahrenheit
* @param {number} c - température en °C
* @returns {number} température en °F
*/
function celsiusToFahrenheit(c) {
return (9/5) * c + 32;
}
/**
* Convertit Fahrenheit → Celsius
* @param {number} f - température en °F
* @returns {number} température en °C
*/
function fahrenheitToCelsius(f) {
return (5/9) * (f - 32);
}
/**
* Met à jour l'affichage en fonction du champ modifié
*/
function mettreAJour() {
const celsiusVal = parseFloat(celsiusInput.value);
if (!isNaN(celsiusVal)) {
const f = celsiusToFahrenheit(celsiusVal);
fahrenheitOutput.value = f.toFixed(2);
} else {
fahrenheitOutput.value = ""; // champ vide si saisie invalide
}
}
/**
* Gestion de la touche Entrée dans le champ Celsius
*/
function gérerEntrée(e) {
if (e.key === "Enter") {
mettreAJour();
}
}
// écouteurs d’évènements
celsiusInput.addEventListener("blur", mettreAJour); // lorsqu’on quitte le champ
celsiusInput.addEventListener("keydown", gérerEntrée); // touche Entrée
```
**Explication détaillée**
1. **Récupération des nœuds** : `getElementById` renvoie les éléments `<input>` et `<output>`.
2. **Fonctions de conversion** : chacune reçoit un nombre et retourne le résultat selon la formule mathématique. L’utilisation de `return` permet de réutiliser le résultat ailleurs.
3. **`mettreAJour`** : lit la valeur du champ Celsius, la convertit en nombre flottant avec `parseFloat`. Si la conversion échoue (`isNaN` vrai), on vide le champ de sortie ; sinon on calcule le Fahrenheit et on l’affiche avec deux décimales (`toFixed(2)`).
4. **Écouteurs** : `blur` déclenche la mise à jour quand l’utilisateur clique ailleurs ou tabule ; `keydown` vérifie si la touche pressée est `Enter` pour valider immédiatement.
### 21.4 Exemple complet – Convertisseur Euro ↔ Franc CFA
**HTML** (similaire, seuls les IDs changent)
```html
<h1>Convertisseur Euro ↔ Franc CFA</h1>
<div class="block">
<label for="euro">Euro (€)</label>
<input type="number" id="euro" step="0.01">
</div>
<div class="block">
<label for="franc">Franc CFA (FCFA)</label>
<output id="franc"></output>
</div>
<script src="convertisseur_monnaie.js"></script>
```
**JS**
```javascript
const taux = 655.957; // 1 € = 655.957 FCFA (taux fixe)
const euroInput = document.getElementById("euro");
const francOutput = document.getElementById("franc");
function euroToFranc(e) { return e * taux; }
function francToEuro(f) { return f / taux; }
function mettreAJour() {
const euroVal = parseFloat(euroInput.value);
if (!isNaN(euroVal)) {
francOutput.value = euroToFranc(euroVal).toFixed(0);
} else {
francOutput.value = "";
}
}
euroInput.addEventListener("blur", mettreAJour);
euroInput.addEventListener("keydown", e => {
if (e.key === "Enter") mettreAJour();
});
```
**Résultat attendu** : saisir `1` dans le champ Euro affiche `656` dans le champ Franc CFA (arrondi à l’unité). Saisir `13119` dans le champ Franc CFA (via une version symétrique non montrée ici) donnerait `20` € après conversion inverse.
### 21.5 Exercices d’application corrigés
#### Exercice 1 – Fonction qui retourne le plus grand de deux nombres
**Consigne** : Écrire une fonction `maxDeux(a, b)` qui retourne le plus grand des deux arguments. Tester avec les couples `(7, 3)` et `(-2, -8)`.
**Corrigé**
```javascript
function maxDeux(a, b) {
return a > b ? a : b; // opérateur ternaire
}
console.log(maxDeux(7, 3)); // → 7
console.log(maxDeux(-2, -8)); // → -2
```
*Justification* : L’opérateur ternaire évalue la condition `a > b`. Si vraie, il retourne `a`; sinon `b`.
#### Exercice 2 – Gestion d’un évènement `change` sur une liste déroulante
**Consigne** : Une `<select>` contient les options `"Celsius"` et `"Fahrenheit"`. Lorsqu’on change l’option, afficher dans un `<p id="info">` l’unité sélectionnée.
**HTML**
```html
<select id="unite">
<option value="c">Celsius</option>
<option value="f">Fahrenheit</option>
</select>
<p id="info"></p>
```
**JS**
```javascript
document.getElementById("unite").addEventListener("change", function() {
const choix = this.value;
const info = document.getElementById("info");
info.textContent = choix === "c" ? "Vous avez choisi Celsius"
: "Vous avez choisi Fahrenheit";
});
```
*Justification* : L’écouteur `change` se déclenche dès que la valeur du `<select>` est modifiée. La fonction anonyme lit la valeur sélectionnée (`this.value`) et met à jour le texte du paragraphe.
#### Exercice 3 – Convertisseur de kilomètres en miles (1 km = 0.621371 mi)
**Consigne** : Réaliser un convertisseur similaire à celui de la leçon 21, mais avec les unités km et mi. Afficher le résultat avec trois décimales.
**HTML**
```html
<label>Kilomètres : <input type="number" id="km" step="0.001"></label>
<label>Miles : <output id="mi"></output></label>
```
**JS**
```javascript
const facteur = 0.621371;
const kmInput = document.getElementById("km");
const miOutput = document.getElementById("mi");
function kmToMi(k) { return k * facteur; }
function mettreAJour() {
const k = parseFloat(kmInput.value);
if (!isNaN(k)) {
miOutput.value = kmToMi(k).toFixed(3);
} else {
miOutput.value = "";
}
}
kmInput.addEventListener("blur", mettreAJour);
kmInput.addEventListener("keydown", e => {
if (e.key === "Enter") mettreAJour();
});
```
*Justification* : Même schéma que le convertisseur température ; seule la constante de conversion et le nombre de décimales changent.
#### Exercice 4 – Fonction anonyme qui compte les caractères d’un champ texte
**Consigne** : Au fur et à mesure que l’utilisateur tape dans un `<textarea>`, afficher le nombre de caractères saisis dans un `<span id="compteur">`.
**HTML**
```html
<textarea id="texte" rows="4" cols="30"></textarea>
<span id="compteur">0</span> caractères
```
**JS**
```javascript
document.getElementById("texte").addEventListener("input", function() {
const nb = this.value.length;
document.getElementById("compteur").textContent = nb;
});
```
*Justification* : L’évènement `input` se déclenche à chaque modification du contenu du `<textarea>`. La fonction anonyme calcule la longueur de la chaîne (`this.value.length`) et l’affiche.
#### Exercice 5 – Combinaison : fonction qui retourne `true` si un nombre est pair, sinon `false` ; utilisation dans un évènement `click` pour changer la couleur de fond d’une page.
**Consigne** : Créer une fonction `estPair(n)` retournant un booléen. Au clic sur un bouton, lire la valeur d’un champ `<input type="number">`, appeler `estPair`, et si le nombre est pair mettre le fond de la page en vert clair, sinon en rose clair.
**HTML**
```html
<input type="number" id="nombre">
<button id="btn">Tester</button>
```
**JS**
```javascript
function estPair(n) {
return n % 2 === 0; // reste de la division par 2 nul → pair
}
document.getElementById("btn").addEventListener("click", function() {
const n = parseFloat(document.getElementById("nombre").value);
const body = document.body;
if (!isNaN(n) && estPair(n)) {
body.style.backgroundColor = "#c8e6c9"; // vert clair
} else {
body.style.backgroundColor = "#f8bbd0"; // rose clair
}
});
```
*Justification* : Le modulo `%` donne le reste. Si `n % 2 === 0`, le nombre est pair. La fonction renvoie donc un booléen exploitable dans la condition `if`.
---
## Erreurs fréquentes
| # | Erreur classique | Pourquoi elle se produit | Comment l’éviter |
|---|------------------|--------------------------|------------------|
| 1 | Oublier `return` dans une fonction destinée à produire une valeur | La fonction renvoie alors `undefined` et le résultat attendu est perdu. | Toujours vérifier que chaque chemin d’exécution aboutit à un `return` explicite ou à une valeur retournée implicitement (ex. : expression fléchée). |
| 2 | Confondre `=` (affectation) et `==` / `===` (comparaison) dans une condition | L’affectation modifie la variable et la condition devient toujours vraie (ou fausse selon la valeur affectée). | Utiliser `===` pour les comparaisons strictes ; relire les conditions en recherchant un seul `=` entouré d’espaces. |
| 3 | Omettre `event.preventDefault()` lors de la soumission d’un formulaire lorsqu’on veut gérer soi-même la validation | Le navigateur recharge la page ou redirige, écrasant le script en cours. | Ajouter `e.preventDefault();` en première ligne du gestionnaire d’évènement `submit`. |
| 4 | Utiliser une variable déclarée avec `var` dans une boucle et espérer qu’elle soit locale à l’itération | `var` est de portée fonctionnelle, pas blocale ; toutes les itérations partagent la même variable. | Préférer `let` ou `const` pour les variables de boucle afin d’obtenir une portée blocale. |
| 5 | Ne pas convertir la saisie d’un `<input>` en nombre avant de faire un calcul mathématique | La valeur reste une chaîne ; `+` effectue alors une concaténation au lieu d’une addition. | Envelopper la valeur avec `Number()`, `parseFloat()` ou `parseInt()` selon le besoin. |
| 6 | Placer le script `<script>` avant les éléments HTML auxquels il fait référence | Le DOM n’est pas encore construit, `getElementById` renvoie `null`. | Placer le script juste avant la fermeture de `</body>` ou utiliser l’évènement `DOMContentLoaded`. |
---
## Synthèse du chapitre
- **Fonction** : bloc d’instructions nommé, paramètres, retour éventuel (`return`).
- Sans `return` → `undefined`.
- Valeurs par défaut possibles (`param = valeur`).
- Fonctions anonymes et flèches pour des callbacks concis.
- **Évènement DOM** : action utilisateur (click, submit, input…) détectée par `addEventListener(type, fonction)`.
- Propagation (bubbling) et action par défaut (`stopPropagation()`, `preventDefault()`).
- Gestionnaire souvent anonyme ou fléché pour accéder au contexte (`this`, `event`).
- **Convertisseur** : séparation HTML (structure), CSS (présentation), JS (logique).
- Formule de conversion (ex. : $F = \frac{9}{5}C + 32$).
- Mise à jour dynamique via écouteurs (`blur`, `keydown`, `input`).
- Gestion des erreurs de saisie (`isNaN`, champ vide).
- **Bonnes pratiques** : déclarer les constantes avec `const`, utiliser `let` pour les variables qui changent, privilégier les comparaisons strictes (`===`), toujours prévenir le comportement par défaut quand on gère soi-même un évènement, convertir les entrées utilisateur en type numérique avant tout calcul.
---
## Glossaire
| Terme | Définition |
|-------|------------|
| Fonction | Bloc d’instructions réutilisable, éventuellement paramétré, pouvant retourner une valeur. |
| Retour (`return`) | Instruction qui termine l’exécution d’une fonction et renvoie une valeur appelante. |
| Fonction anonyme | Fonction sans nom, souvent affectée à une variable ou passée comme argument. |
| Fonction fléchée | Syntaxe courte `() => { … }` qui lie lexicalement `this`. |
| Évènement DOM | Action de l’utilisateur ou du navigateur (clic, saisie, soumission…) détectable sur un nœud. |
| Écouteur (`addEventListener`) | Méthode qui enregistre une fonction de rappel à exécuter lorsqu’un évènement survient. |
| Propagation | Mécanisme par lequel un évènement remonte du nœud cible vers ses ancêtres (bubbling). |
| Action par défaut | Comportement intrinsèque du navigateur lié à un évènement (ex. : soumission de formulaire). |
| `preventDefault()` | Méthode qui annule l’action par défaut d’un évènement. |
| `stopPropagation()` | Méthode qui empêche la propagation supplémentaire de l’évènement dans l’arbre DOM. |
| `parseFloat` | Fonction qui convertit une chaîne en nombre à virgule flottante, renvoyant `NaN` si échec. |
| `isNaN` | Fonction qui teste si une valeur est égale à la valeur spéciale `NaN` (Not‑a‑Number). |
| `innerHTML` / `textContent` | Propriétés permettant de lire ou modifier le contenu HTML ou texte d’un nœud. |
| `blur` | Évènement déclenché lorsqu’un élément perd le focus. |
| `keydown` | Évènement déclenché lorsqu’une touche du clavier est pressée. |
| `input` | Évènement déclenché à chaque modification de la valeur d’un champ `<input>`, `<select>` ou `<textarea>$. |
---
*Fin du cours.*
Quiz du chapitre
10 questions — vérifie chaque réponse pour voir l'explication.